From 48540940b6c28bb4378abfeb500ec45a625b37b6 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 15 May 2012 10:38:20 +0000 Subject: initial commit git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/modernb/modern_skinengine.cpp | 4884 +++++++++++++++++++++++++++++++++ 1 file changed, 4884 insertions(+) create mode 100644 plugins/modernb/modern_skinengine.cpp (limited to 'plugins/modernb/modern_skinengine.cpp') diff --git a/plugins/modernb/modern_skinengine.cpp b/plugins/modernb/modern_skinengine.cpp new file mode 100644 index 0000000000..54a6c8011c --- /dev/null +++ b/plugins/modernb/modern_skinengine.cpp @@ -0,0 +1,4884 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +//Include +#include "hdr/modern_commonheaders.h" +#include +#include "m_api/m_skin_eng.h" +#include "hdr/modern_skinselector.h" +#include "hdr/modern_cluiframes.h" + +#define _EFFECTENUM_FULL_H +#include "hdr/modern_effectenum.h" +#undef _EFFECTENUM_FULL_H + +#include "hdr/modern_skinengine.h" +#include "hdr/modern_commonprototypes.h" +#include +#include "hdr/modern_sync.h" +//Implementation + +/* Global variables */ + +SKINOBJECTSLIST g_SkinObjectList={0}; +CURRWNDIMAGEDATA * g_pCachedWindow=NULL; + +BOOL (WINAPI *g_proc_UpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD); + +BOOL g_flag_bPostWasCanceled =FALSE; +BOOL g_flag_bFullRepaint =FALSE; +BOOL g_mutex_bLockUpdating =FALSE; + +SortedList * gl_plGlyphTexts=NULL; +SortedList * gl_plSkinFonts =NULL; + +/* Private module variables */ + +static HANDLE hSkinLoadedEvent; + +static GLYPHIMAGE * pLoadedImages=NULL; +static DWORD dwLoadedImagesCount=0; +static DWORD dwLoadedImagesAlocated=0; + +static BOOL flag_bUpdateQueued=FALSE; +static BOOL flag_bJustDrawNonFramedObjects=FALSE; +static BOOL mutex_bLockUpdate=FALSE; + +static SortedList * pEffectStack=NULL; +static SKINOBJECTSLIST * pCurrentSkin=NULL; +static char ** pszSettingName=NULL; +static int nArrayLen=0; +static char * iniCurrentSection=NULL; +static char * szFileName=NULL; + +static BYTE pbGammaWeight[256]={0}; +static BYTE pbGammaWeightAdv[256]={0}; +static BOOL bGammaWeightFilled=FALSE; + +static CRITICAL_SECTION cs_SkinChanging={0}; + + +/* Private module procedures */ +static BOOL ske_GetMaskBit(BYTE *line, int x); +static INT_PTR ske_Service_AlphaTextOut(WPARAM wParam,LPARAM lParam); +static INT_PTR ske_Service_DrawIconEx(WPARAM wParam,LPARAM lParam); + +static int ske_AlphaTextOut (HDC hDC, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format, DWORD ARGBcolor); +static void ske_AddParseTextGlyphObject(char * szGlyphTextID,char * szDefineString,SKINOBJECTSLIST *Skin); +static void ske_AddParseSkinFont(char * szFontID,char * szDefineString,SKINOBJECTSLIST *Skin); +static int ske_DeleteAllSettingInSection(char * SectionName); +static int ske_GetSkinFromDB(char * szSection, SKINOBJECTSLIST * Skin); +static LPSKINOBJECTDESCRIPTOR ske_FindObject(const char * szName, BYTE objType,SKINOBJECTSLIST* Skin); +static HBITMAP ske_LoadGlyphImageByDecoders(char * szFileName); +static int ske_LoadSkinFromResource(BOOL bOnlyObjects); +static void ske_PreMultiplyChanells(HBITMAP hbmp,BYTE Mult); +static int ske_ValidateSingleFrameImage(FRAMEWND * Frame, BOOL SkipBkgBlitting); +static INT_PTR ske_Service_UpdateFrameImage(WPARAM wParam, LPARAM lParam); +static INT_PTR ske_Service_InvalidateFrameImage(WPARAM wParam, LPARAM lParam); +static INT_PTR ske_Service_DrawTextWithEffect( WPARAM wParam, LPARAM lParam ); + +//Decoders +static HMODULE hImageDecoderModule; + +typedef DWORD (__stdcall *pfnImgNewDecoder)(void ** ppDecoder); +static pfnImgNewDecoder ImgNewDecoder; + +typedef DWORD (__stdcall *pfnImgDeleteDecoder)(void * pDecoder); +static pfnImgDeleteDecoder ImgDeleteDecoder; + +typedef DWORD (__stdcall *pfnImgNewDIBFromFile)(LPVOID /*in*/pDecoder, LPCSTR /*in*/pFileName, LPVOID /*out*/*pImg); +static pfnImgNewDIBFromFile ImgNewDIBFromFile; + +typedef DWORD (__stdcall *pfnImgDeleteDIBSection)(LPVOID /*in*/pImg); +static pfnImgDeleteDIBSection ImgDeleteDIBSection; + +typedef DWORD (__stdcall *pfnImgGetHandle)(LPVOID /*in*/pImg, HBITMAP /*out*/*pBitmap, LPVOID /*out*/*ppDIBBits); +static pfnImgGetHandle ImgGetHandle; + +static MODERNEFFECT meCurrentEffect={-1,{0},0,0}; + + +////////////////////////////////////////////////////////////////////////// +// Ini file parser +////////////////////////////////////////////////////////////////////////// +IniParser::IniParser( TCHAR * tcsFileName, BYTE flags ) : _Flags( flags ) +{ + _DoInit(); + if ( !tcsFileName ) return; + + if ( tcsFileName[0] == _T('%') ) + { + //TODO: Add parser of resource filename here + _LoadResourceIni( g_hInst, MAKEINTRESOURCEA(IDR_MSF_DEFAULT_SKIN), "MSF"); + return; + } + + _hFile = _tfopen( tcsFileName, _T("r") ); + + if ( _hFile != NULL ) + { + _eType = IT_FILE; + _isValid = true; + } +} + +IniParser::IniParser( HINSTANCE hInst, const char * resourceName, const char * resourceType, BYTE flags ) : _Flags( flags ) +{ + _DoInit(); + _LoadResourceIni( hInst, resourceName, resourceType ); +} + +IniParser::~IniParser() +{ + if ( _szSection ) mir_free( _szSection ); + if ( _hFile ) fclose( _hFile ); + if ( _hGlobalRes ) + { + UnlockResource( _hGlobalRes ); + FreeResource(_hGlobalRes); + } + + _szSection = NULL; + _hGlobalRes = NULL; + _hFile = NULL; + _isValid = false; + _eType = IT_UNKNOWN; +} + +HRESULT IniParser::Parse( ParserCallback_t pLineCallBackProc, LPARAM SecCheck ) +{ + if ( _isValid && pLineCallBackProc ) + { + _pLineCallBackProc = pLineCallBackProc; + _SecCheck = SecCheck; + switch ( _eType ) + { + case IT_FILE: + return _DoParseFile(); + case IT_RESOURCE: + return _DoParseResource(); + } + } + return E_FAIL; +} + + +HRESULT IniParser::WriteStrToDb( const char * szSection, const char * szName, const char * szValue, IniParser * This ) +{ + if ( This->_SecCheck) + { + //TODO check security here + if ( wildcmp( szSection,"Skin_Description_Section",1 ) ) return S_OK; + } + if ( ( This->_Flags == IniParser::FLAG_ONLY_OBJECTS ) && !wildcmp( szSection, DEFAULTSKINSECTION,1 ) ) + return S_OK; // skip not objects + + +// if ( strlen(szValue)>0 && szValue[strlen(szValue)-1]=='\n' ) +// szValue[strlen(szValue)-1]='\0'; //kill linefeed at the end + + switch(szValue[0]) + { + case 'b': + { + BYTE P; + P=(BYTE)atoi(szValue+1); + ModernWriteSettingByte(NULL,szSection,szName,P); + } + break; + case 'w': + { + WORD P; + P=(WORD)atoi(szValue+1); + ModernWriteSettingWord(NULL,szSection,szName,P); + } + break; + case 'd': + { + DWORD P; + P=(DWORD)atoi(szValue+1); + ModernWriteSettingDword(NULL,szSection,szName,P); + } + break; + case 's': + ModernWriteSettingString(NULL,szSection,szName,szValue+1); + break; + case 'f': + if (szFileName) + { + char fn[MAX_PATH]={0}; + char bb[MAX_PATH*2]={0}; + int pp, i; + pp=-1; + CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)szFileName, (LPARAM)fn); + { + for (i=strlen(fn); i>=0; i--) if (fn[i]=='.') break; + if (i>0) fn[i]='\0'; + } + _snprintf(bb,SIZEOF(bb),"%s\\%s",fn,szValue+1); + ModernWriteSettingString(NULL,szSection,szName,bb); + } + break; + } + return S_OK; +} +int IniParser::GetSkinFolder( IN const TCHAR * szFileName, OUT TCHAR * pszFolderName ) +{ + TCHAR *pszPos; + TCHAR *szBuff; + + szBuff = mir_tstrdup( szFileName ); + pszPos = szBuff + _tcslen( szBuff ); + while ( pszPos > szBuff && *pszPos!= _T('.') ) { pszPos--; } + *pszPos=_T('\0'); + _tcscpy( pszFolderName, szBuff ); + + TCHAR custom_folder[MAX_PATH]; + TCHAR cus[MAX_PATH]; + TCHAR *b3; + _tcscpy( custom_folder, pszFolderName ); + b3=custom_folder + _tcslen( custom_folder ); + while ( b3 > custom_folder && *b3!= _T('\\') ) { b3--; } + *b3=_T('\0'); + + GetPrivateProfileString(_T("Skin_Description_Section"),_T("SkinFolder"),_T(""),cus,SIZEOF(custom_folder),szFileName); + if ( cus && _tcslen(cus)>0) + _sntprintf(pszFolderName,MAX_PATH,_T("%s\\%s"),custom_folder,cus); + + mir_free_and_nill(szBuff); + CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)pszFolderName, (LPARAM)pszFolderName); + + return 0; +} +void IniParser::_DoInit() +{ + _isValid = false; + _eType = IT_UNKNOWN; + _szSection = NULL; + _hFile = NULL; + _hGlobalRes = NULL; + _dwSizeOfRes = 0; + _pPosition = NULL; + _pLineCallBackProc = NULL; + _SecCheck = 0; + +} + +void IniParser::_LoadResourceIni( HINSTANCE hInst, const char * resourceName, const char * resourceType ) +{ + + if( _eType != IT_UNKNOWN ) return; + + HRSRC hRSrc = FindResourceA( hInst, resourceName, resourceType ); + if ( !hRSrc ) return; + + _hGlobalRes=LoadResource( hInst, hRSrc ); + if ( !_hGlobalRes ) return; + + _dwSizeOfRes = SizeofResource( hInst, hRSrc ); + _pPosition =(char*) LockResource( _hGlobalRes ); + + _isValid = true; + _eType = IT_RESOURCE; + +} + + + +HRESULT IniParser::_DoParseFile() +{ + char szLine[MAX_LINE_LEN]; + _nLine = 0; + while ( fgets( szLine, SIZEOF(szLine), _hFile ) != NULL ) + { + size_t len = 0; + char * pLine = (char*)_RemoveTailings( szLine, len ); + if ( len > 0 ) + { + pLine[len]='\0'; + if ( !_DoParseLine( pLine ) ) return E_FAIL; + } + else + _nLine++; + }; + + return S_OK; +} + +HRESULT IniParser::_DoParseResource() +{ + _nLine = 0; + char szLine[MAX_LINE_LEN]; + char * pos = ( char* ) _pPosition; + + while ( pos < _pPosition + _dwSizeOfRes ) + { + int i=0; + while ( pos < _pPosition + _dwSizeOfRes && *pos != '\n' && *pos!= '\0' && i < MAX_LINE_LEN - 1 ) + { + if ( (*pos) != '\r' ) + szLine[ i++ ] = *pos; + pos++; + } + szLine[ i ]='\0'; + pos++; + + size_t len = 0; + char * pLine = (char*) _RemoveTailings( szLine, len ); + if ( len > 0 ) + { + pLine[len]='\0'; + if ( !_DoParseLine( pLine ) ) return E_FAIL; + } + else + _nLine++; + } + return S_OK; +} + +const char * IniParser::_RemoveTailings( const char * szLine, size_t& len ) +{ + const char * pStart = szLine; + while( *pStart == ' ' || *pStart=='\t' ) pStart++; //skip spaces at begin + const char * pEnd = pStart + strlen( pStart ); + while( pEnd > pStart && ( *pEnd == ' ' || *pEnd == '\t' || *pEnd == '\n' || *pEnd == '\r' ) ) pEnd--; + + len = pEnd - pStart; + return pStart; +} + +BOOL IniParser::_DoParseLine( char * szLine ) +{ + _nLine++; + DWORD len = strlen( szLine ); + + if ( len == 0 ) return TRUE; + + switch( szLine[0] ) + { + case ';': + return TRUE; // start of comment is found + case '[': + { + //New section start here + if ( _szSection ) mir_free( _szSection ); + _szSection = NULL; + + char *tbuf = szLine + 1; // skip [ + + char *ebuf= tbuf; + + while ( *ebuf != ']' && *ebuf !='\0' ) ebuf++; + if ( *ebuf == '\0' ) + return FALSE; // no close bracket + + DWORD sectionLen = ebuf - tbuf; + _szSection = (char*) mir_alloc( sectionLen + 1 ); + strncpy( _szSection, tbuf, sectionLen ); + _szSection[sectionLen]='\0'; + } + return TRUE; + + default: + if ( !_szSection ) + return TRUE; //param found out of section + + char *keyName=szLine; + char *keyValue=szLine; + + DWORD eqPlace=0; + DWORD len2=strlen(keyName); + + while ( eqPlace < len2 && keyName[ eqPlace ] != '=' ) + eqPlace++; //find '=' + + if (eqPlace==0 || eqPlace==len2) + return TRUE; //= not found or no key name //say false + + keyName[eqPlace] = '\0'; + + keyValue = keyName + eqPlace + 1; + + //remove tail spaces in Name + { + DWORD len3=strlen(keyName); + int j=len3-1; + while (j>0 && (keyName[j]==' ' || keyName[j]=='\t')) j--; + if (j>=0) keyName[j+1]='\0'; + } + //remove start spaces in Value + { + DWORD len3=strlen(keyValue); + DWORD j=0; + while (j0 && (keyValue[j]==' ' || keyValue[j]=='\t' || keyValue[j]=='\n')) j--; + if (j>=0) keyValue[j+1]='\0'; + } + _pLineCallBackProc( _szSection, keyName, keyValue, this ); + } + return TRUE; +} +////////////////////////////////////////////////////////////////////////// +// End of IniParser +////////////////////////////////////////////////////////////////////////// + +HRESULT SkinEngineLoadModule() +{ + ModernSkinButtonLoadModule(); + InitializeCriticalSection(&cs_SkinChanging); + MainModernMaskList=(LISTMODERNMASK*)mir_calloc(sizeof(LISTMODERNMASK)); + //init variables + g_SkinObjectList.dwObjLPAlocated=0; + g_SkinObjectList.dwObjLPReserved=0; + g_SkinObjectList.pObjects=NULL; + // Initialize GDI+ + InitGdiPlus(); + AniAva_InitModule(); + //load decoder + hImageDecoderModule=NULL; + if (g_CluiData.fGDIPlusFail) + { + hImageDecoderModule = LoadLibrary(TEXT("ImgDecoder.dll")); + if (hImageDecoderModule==NULL) + { + char tDllPath[ MAX_PATH ]; + GetModuleFileNameA( g_hInst, tDllPath, sizeof( tDllPath )); + { + char* p = strrchr( tDllPath, '\\' ); + if ( p != NULL ) + strcpy( p+1, "ImgDecoder.dll" ); + else + { + strcpy( tDllPath, "ImgDecoder.dll" ); + } + } + + hImageDecoderModule = LoadLibraryA(tDllPath); + } + if (hImageDecoderModule!=NULL) + { + ImgNewDecoder=(pfnImgNewDecoder )GetProcAddress( hImageDecoderModule, "ImgNewDecoder"); + ImgDeleteDecoder=(pfnImgDeleteDecoder )GetProcAddress( hImageDecoderModule, "ImgDeleteDecoder"); + ImgNewDIBFromFile=(pfnImgNewDIBFromFile)GetProcAddress( hImageDecoderModule, "ImgNewDIBFromFile"); + ImgDeleteDIBSection=(pfnImgDeleteDIBSection)GetProcAddress( hImageDecoderModule, "ImgDeleteDIBSection"); + ImgGetHandle=(pfnImgGetHandle)GetProcAddress( hImageDecoderModule, "ImgGetHandle"); + } + } + //create services + CreateServiceFunction(MS_SKIN_DRAWGLYPH,ske_Service_DrawGlyph); + CreateServiceFunction(MS_SKINENG_UPTATEFRAMEIMAGE,ske_Service_UpdateFrameImage); + CreateServiceFunction(MS_SKINENG_INVALIDATEFRAMEIMAGE,ske_Service_InvalidateFrameImage); + CreateServiceFunction(MS_SKINENG_ALPHATEXTOUT,ske_Service_AlphaTextOut); + CreateServiceFunction(MS_SKINENG_DRAWICONEXFIX,ske_Service_DrawIconEx); + + CreateServiceFunction(MS_DRAW_TEXT_WITH_EFFECT,ske_Service_DrawTextWithEffect); + + //create event handle + hSkinLoadedEvent=ModernHookEvent(ME_SKIN_SERVICESCREATED,CLUI_OnSkinLoad); + NotifyEventHooks(g_CluiData.hEventSkinServicesCreated,0,0); + return S_OK; +} + +int SkinEngineUnloadModule() +{ + //unload services + ModernUnhookEvent(hSkinLoadedEvent); + ModernSkinButtonUnloadModule(0,0); + ske_UnloadSkin(&g_SkinObjectList); + if (g_SkinObjectList.pObjects) + mir_free_and_nill(g_SkinObjectList.pObjects); + if (g_SkinObjectList.pMaskList) + mir_free_and_nill(g_SkinObjectList.pMaskList); + if (MainModernMaskList) + mir_free_and_nill(MainModernMaskList); + if (pEffectStack) + { + int i; + for (i=0; irealCount; i++) + if (pEffectStack->items[i]) + { + EFFECTSSTACKITEM * effect=(EFFECTSSTACKITEM*)(pEffectStack->items[i]); + mir_free_and_nill(effect); + } + li.List_Destroy(pEffectStack); + mir_free_and_nill(pEffectStack); + } + if (g_pCachedWindow) + { + SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackOld); + SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageOld); + DeleteObject(g_pCachedWindow->hBackDIB); + DeleteObject(g_pCachedWindow->hImageDIB); + mod_DeleteDC(g_pCachedWindow->hBackDC); + mod_DeleteDC(g_pCachedWindow->hImageDC); + ReleaseDC(NULL,g_pCachedWindow->hScreenDC); + mir_free_and_nill(g_pCachedWindow); + g_pCachedWindow=NULL; + } + DeleteCriticalSection(&cs_SkinChanging); + GdiFlush(); + DestroyServiceFunction((HANDLE)MS_SKIN_REGISTEROBJECT); + DestroyServiceFunction((HANDLE)MS_SKIN_DRAWGLYPH); + DestroyHookableEvent(g_CluiData.hEventSkinServicesCreated); + if (hImageDecoderModule) FreeLibrary(hImageDecoderModule); + AniAva_UnloadModule(); + ShutdownGdiPlus(); + //free variables + return 1; +} + + + +BOOL ske_AlphaBlend(HDC hdcDest,int nXOriginDest,int nYOriginDest,int nWidthDest,int nHeightDest,HDC hdcSrc,int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc,BLENDFUNCTION blendFunction) +{ + if (g_CluiData.fDisableSkinEngine && !(!g_CluiData.fGDIPlusFail && blendFunction.BlendFlags&128)) + { + if (nWidthDest!=nWidthSrc || nHeightDest!=nHeightSrc) + return StretchBlt(hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest,hdcSrc,nXOriginSrc,nYOriginSrc,nWidthSrc,nHeightSrc, SRCCOPY); + else + return BitBlt(hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest,hdcSrc,nXOriginSrc,nYOriginSrc, SRCCOPY); + } + + if (!g_CluiData.fGDIPlusFail && blendFunction.BlendFlags&128 ) //Use gdi+ engine + { + return GDIPlus_AlphaBlend( hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest, + hdcSrc,nXOriginSrc,nYOriginSrc,nWidthSrc,nHeightSrc, + &blendFunction); + } + blendFunction.BlendFlags&=~128; + return AlphaBlend(hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest,hdcSrc,nXOriginSrc,nYOriginSrc,nWidthSrc,nHeightSrc,blendFunction); +} + + +static int ske_LockSkin() +{ + EnterCriticalSection(&cs_SkinChanging); + return 0; +} +static int ske_UnlockSkin() +{ + LeaveCriticalSection(&cs_SkinChanging); + return 0; +} + +typedef struct _tagDCBuffer +{ + HDC hdcOwnedBy; + int nUsageID; + int width; + int height; + void* pImage; + HDC hDC; + HBITMAP oldBitmap; + HBITMAP hBitmap; + DWORD dwDestroyAfterTime; +}DCBUFFER; +CRITICAL_SECTION BufferListCS={0}; + +SortedList * BufferList=NULL; +enum +{ + BUFFER_DRAWICON=0, + BUFFER_DRAWIMAGE +}; + +int SortBufferList(void* it1, void * it2) +{ + DCBUFFER * buf1=(DCBUFFER *)it1; + DCBUFFER * buf2=(DCBUFFER *)it2; + if (buf1->hdcOwnedBy!=buf2->hdcOwnedBy) return (int)(buf1->hdcOwnedBy < buf2->hdcOwnedBy); + else if (buf1->nUsageID!=buf2->nUsageID) return (int) (buf1->nUsageID < buf2->nUsageID); + else return (int) (buf1->hDC < buf2->hDC); +} + +HDC ske_RequestBufferDC(HDC hdcOwner, int dcID, int width, int height, BOOL fClear) +{ + DCBUFFER buf; + DCBUFFER * pBuf; + if (BufferList==NULL) + { + BufferList=li.List_Create(0,2); + BufferList->sortFunc=SortBufferList; + InitializeCriticalSection(&BufferListCS); + } + EnterCriticalSection(&BufferListCS); + //Try to find DC in buffer list + buf.hdcOwnedBy=hdcOwner; + buf.nUsageID=dcID; + buf.hDC=NULL; + pBuf=(DCBUFFER*)li.List_Find(BufferList,(void*)&buf); + if (!pBuf) + { + //if not found - allocate it + pBuf=(DCBUFFER *)mir_alloc(sizeof(DCBUFFER)); + *pBuf=buf; + pBuf->width=width; + pBuf->height=height; + pBuf->hBitmap=ske_CreateDIB32Point(width,height,&(pBuf->pImage)); + pBuf->hDC=CreateCompatibleDC(hdcOwner); + pBuf->oldBitmap=(HBITMAP)SelectObject(pBuf->hDC,pBuf->hBitmap); + pBuf->dwDestroyAfterTime=0; + li.List_InsertPtr(BufferList,pBuf); + } + else + { + if (pBuf->width!=width || pBuf->height!=height) + { + //resize + SelectObject(pBuf->hDC,pBuf->oldBitmap); + DeleteObject(pBuf->hBitmap); + pBuf->width=width; + pBuf->height=height; + pBuf->hBitmap=ske_CreateDIB32Point(width,height,&(pBuf->pImage)); + pBuf->oldBitmap=(HBITMAP)SelectObject(pBuf->hDC,pBuf->hBitmap); + } else if (fClear) + memset(pBuf->pImage,0,width*height*sizeof(DWORD)); + } + pBuf->dwDestroyAfterTime=0; + LeaveCriticalSection(&BufferListCS); + return pBuf->hDC; +} + +int ske_ReleaseBufferDC(HDC hDC, int keepTime) +{ + DWORD dwCurrentTime=GetTickCount(); + DCBUFFER * pBuf=NULL; + //Try to find DC in buffer list - set flag to be release after time; + int i=0; + EnterCriticalSection(&BufferListCS); + for (i=0; irealCount; i++) + { + pBuf=(DCBUFFER *)BufferList->items[i]; + if (pBuf) + { + if (hDC!=NULL && pBuf->hDC==hDC) + { + pBuf->dwDestroyAfterTime=dwCurrentTime+keepTime; + break; + } + else + { + if ((pBuf->dwDestroyAfterTime && pBuf->dwDestroyAfterTime < dwCurrentTime) || keepTime==-1) + { + SelectObject(pBuf->hDC,pBuf->oldBitmap); + DeleteObject(pBuf->hBitmap); + DeleteDC(pBuf->hDC); + mir_free(pBuf); + li.List_Remove(BufferList,i); + i--; + } + } + } + } + LeaveCriticalSection(&BufferListCS); + return 0; +} + +BOOL ske_SetRgnOpaque(HDC memdc,HRGN hrgn, BOOL force) +{ + RGNDATA * rdata; + DWORD rgnsz; + DWORD d; + RECT * rect; + if (g_CluiData.fDisableSkinEngine && !force) return TRUE; + rgnsz=GetRegionData(hrgn,0,NULL); + rdata=(RGNDATA *) mir_alloc(rgnsz); + GetRegionData(hrgn,rgnsz,rdata); + rect=(RECT *)rdata->Buffer; + for (d=0; drdh.nCount; d++) + { + ske_SetRectOpaque(memdc,&rect[d], force); + } + mir_free_and_nill(rdata); + return TRUE; +} + + +BOOL ske_SetRectOpaque(HDC memdc,RECT *fr, BOOL force) +{ + int f=0; + BYTE * bits; + BITMAP bmp; + HBITMAP hbmp; + + if ( g_CluiData.fDisableSkinEngine && !force ) + return TRUE; + + hbmp=(HBITMAP)GetCurrentObject( memdc,OBJ_BITMAP ); + GetObject( hbmp, sizeof(bmp), &bmp ); + + if ( bmp.bmPlanes != 1 ) + return FALSE; + + if (!bmp.bmBits) + { + f=1; + bits=(BYTE*)malloc(bmp.bmWidthBytes*bmp.bmHeight); + GetBitmapBits(hbmp,bmp.bmWidthBytes*bmp.bmHeight,bits); + } + else + bits=(BYTE*)bmp.bmBits; + + int sx =( fr->left > 0 ) ? fr->left : 0; + int sy =( fr->top > 0 ) ? fr->top : 0; + int ex =( fr->right < bmp.bmWidth ) ? fr->right : bmp.bmWidth; + int ey =( fr->bottombottom : bmp.bmHeight; + + int width=ex-sx; + + BYTE* pLine = ((BYTE*)bits) + (bmp.bmHeight-sy-1)*bmp.bmWidthBytes + (sx << 2) + 3; + for ( int y = 0; y < (ey - sy); y++ ) + { + BYTE * pColumn = pLine; + for ( int x = 0; x < width; x++ ) + { + *pColumn = 255; + pColumn += 4; + } + pLine -= bmp.bmWidthBytes; + } + if (f) + { + SetBitmapBits(hbmp,bmp.bmWidthBytes*bmp.bmHeight,bits); + free(bits); + } + // DeleteObject(hbmp); + return 1; +} + +static BOOL ske_SkinFillRectByGlyph(HDC hDest, HDC hSource, RECT * rFill, RECT * rGlyph, RECT * rClip, BYTE mode, BYTE drawMode, int depth) +{ + int destw=0, desth=0; + int xstart=0, xmax=0; + int ystart=0, ymax=0; + BLENDFUNCTION bfa={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; + BLENDFUNCTION bf={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; + + //initializations + if (mode==FM_STRETCH) + { + HDC mem2dc; + HBITMAP mem2bmp, oldbmp; + RECT wr; + IntersectRect(&wr,rClip,rFill); + if ((wr.bottom-wr.top)*(wr.right-wr.left)==0) return 0; + if (drawMode!=2) + { + mem2dc=CreateCompatibleDC(hDest); + mem2bmp=ske_CreateDIB32(wr.right-wr.left,wr.bottom-wr.top); + oldbmp=(HBITMAP)SelectObject(mem2dc,mem2bmp); + + } + + if (drawMode==0 || drawMode==2) + { + if (drawMode==0) + { + ske_AlphaBlend(mem2dc,rFill->left-wr.left,rFill->top-wr.top,rFill->right-rFill->left,rFill->bottom-rFill->top, + hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,rGlyph->bottom-rGlyph->top,bf); + ske_AlphaBlend(hDest,wr.left,wr.top,wr.right-wr.left, wr.bottom -wr.top,mem2dc,0,0,wr.right-wr.left, wr.bottom -wr.top,bf); + } + else + { + ske_AlphaBlend(hDest,rFill->left,rFill->top,rFill->right-rFill->left,rFill->bottom-rFill->top, + hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,rGlyph->bottom-rGlyph->top,bf); + + } + } + else + { + // BLENDFUNCTION bf={AC_SRC_OVER, 0, 255, 0 }; + ske_AlphaBlend(mem2dc,rFill->left-wr.left,rFill->top-wr.top,rFill->right-rFill->left,rFill->bottom-rFill->top, + hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,rGlyph->bottom-rGlyph->top,bf); + ske_AlphaBlend(hDest,wr.left,wr.top,wr.right-wr.left, wr.bottom -wr.top,mem2dc,0,0,wr.right-wr.left, wr.bottom -wr.top,bf); + } + if (drawMode!=2) + { + SelectObject(mem2dc,oldbmp); + DeleteObject(mem2bmp); + mod_DeleteDC(mem2dc); + } + return 1; + } + else if (mode==FM_TILE_VERT && (rGlyph->bottom-rGlyph->top>0)&& (rGlyph->right-rGlyph->left>0)) + { + HDC mem2dc; + HBITMAP mem2bmp,oldbmp; + RECT wr; + IntersectRect(&wr,rClip,rFill); + if ((wr.bottom-wr.top)*(wr.right-wr.left)==0) return 0; + mem2dc=CreateCompatibleDC(hDest); + //SetStretchBltMode(mem2dc, HALFTONE); + mem2bmp=ske_CreateDIB32(wr.right-wr.left, rGlyph->bottom-rGlyph->top); + oldbmp=(HBITMAP)SelectObject(mem2dc,mem2bmp); + if (!oldbmp) + return 0; + + /// draw here + { + int y=0, sy=0, maxy=0; + int w=rFill->right-rFill->left; + int h=rGlyph->bottom-rGlyph->top; + if (h>0 && (wr.bottom-wr.top)*(wr.right-wr.left)!=0) + { + w=wr.right-wr.left; + { + // BLENDFUNCTION bf={AC_SRC_OVER, 0, 255, 0 }; + ske_AlphaBlend(mem2dc,-(wr.left-rFill->left),0,rFill->right-rFill->left,h,hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,h,bf); + //StretchBlt(mem2dc,-(wr.left-rFill->left),0,rFill->right-rFill->left,h,hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,h,SRCCOPY); + } + if (drawMode==0 || drawMode==2) + { + if (drawMode==0 ) + { + + int dy; + dy=(wr.top-rFill->top)%h; + if (dy>=0) + { + int ht; + y=wr.top; + ht=(y+h-dy<=wr.bottom)?(h-dy):(wr.bottom-wr.top); + BitBlt(hDest,wr.left,y,w,ht,mem2dc,0,dy,SRCCOPY); + } + + y=wr.top+h-dy; + while (ytop)%h; + + if (dy>=0) + { + int ht; + y=wr.top; + ht=(y+h-dy<=wr.bottom)?(h-dy):(wr.bottom-wr.top); + ske_AlphaBlend(hDest,wr.left,y,w,ht,mem2dc,0,dy,w,ht,bf); + } + + y=wr.top+h-dy; + while (yright-rGlyph->left>0)&& (rGlyph->bottom-rGlyph->top>0)&&(rFill->bottom-rFill->top)>0 && (rFill->right-rFill->left)>0) + { + HDC mem2dc; + RECT wr; + HBITMAP mem2bmp,oldbmp; + int w=rGlyph->right-rGlyph->left; + int h=rFill->bottom-rFill->top; + IntersectRect(&wr,rClip,rFill); + if ((wr.bottom-wr.top)*(wr.right-wr.left)==0) return 0; + h=wr.bottom-wr.top; + mem2dc=CreateCompatibleDC(hDest); + + mem2bmp=ske_CreateDIB32(w,h); + oldbmp=(HBITMAP)SelectObject(mem2dc,mem2bmp); + + if (!oldbmp) + return 0; + /// draw here + { + int x=0, sy=0, maxy=0; + { + //SetStretchBltMode(mem2dc, HALFTONE); + //StretchBlt(mem2dc,0,0,w,h,hSource,rGlyph->left+(wr.left-rFill->left),rGlyph->top,w,h,SRCCOPY); + + // BLENDFUNCTION bf={AC_SRC_OVER, 0, 255, 0 }; + ske_AlphaBlend(mem2dc,0,-(wr.top-rFill->top),w,rFill->bottom-rFill->top,hSource,rGlyph->left,rGlyph->top,w,rGlyph->bottom-rGlyph->top,bf); + if (drawMode==0 || drawMode==2) + { + if (drawMode==0) + { + + int dx; + dx=(wr.left-rFill->left)%w; + if (dx>=0) + { + int wt; + x=wr.left; + wt=(x+w-dx<=wr.right)?(w-dx):(wr.right-wr.left); + BitBlt(hDest,x,wr.top,wt,h,mem2dc,dx,0,SRCCOPY); + } + x=wr.left+w-dx; + while (xleft)%w; + x=wr.left-dx; + while (xleft)%w; + if (dx>=0) + { + int wt; + x=wr.left; + wt=(x+w-dx<=wr.right)?(w-dx):(wr.right-wr.left); + ske_AlphaBlend(hDest,x,wr.top,wt,h,mem2dc,dx,0,wt,h,bf); + } + x=wr.left+w-dx; + while (xright-rGlyph->left>0) && (rGlyph->bottom-rGlyph->top>0)) + { + HDC mem2dc; + int w=rGlyph->right-rGlyph->left; + int x=0, sy=0, maxy=0; + int h=rFill->bottom-rFill->top; + HBITMAP mem2bmp,oldbmp; + RECT wr; + IntersectRect(&wr,rClip,rFill); + if ((wr.bottom-wr.top)*(wr.right-wr.left)==0) return 0; + mem2dc=CreateCompatibleDC(hDest); + mem2bmp=ske_CreateDIB32(w,wr.bottom-wr.top); + h=wr.bottom-wr.top; + oldbmp=(HBITMAP)SelectObject(mem2dc,mem2bmp); +#ifdef _DEBUG + if (!oldbmp) + (NULL,"Tile bitmap not selected","ERROR", MB_OK); +#endif + /// draw here + { + + //fill temp bitmap + { + int y; + int dy; + dy=(wr.top-rFill->top)%(rGlyph->bottom-rGlyph->top); + y=-dy; + while (ybottom-rGlyph->top, hSource,rGlyph->left,rGlyph->top,w,rGlyph->bottom-rGlyph->top,bf); + y+=rGlyph->bottom-rGlyph->top; + } + + //-- + //end temp bitmap + if (drawMode==0 || drawMode==2) + { + if (drawMode==0) + { + + int dx; + dx=(wr.left-rFill->left)%w; + if (dx>=0) + { + int wt; + x=wr.left; + wt=(x+w-dx<=wr.right)?(w-dx):(wr.right-wr.left); + BitBlt(hDest,x,wr.top,wt,h,mem2dc,dx,0,SRCCOPY); + } + x=wr.left+w-dx; + while (xleft)%w; + x=wr.left-dx; + while (xleft)%w; + if (dx>=0) + { + int wt; + x=wr.left; + wt=(x+w-dx<=wr.right)?(w-dx):(wr.right-wr.left); + ske_AlphaBlend(hDest,x,wr.top,wt,h,mem2dc,dx,0,wt,h,bf); + } + x=wr.left+w-dx; + while (xhImageDIBByte; + + int x,y; + unsigned int cRect = 64; + PRGNDATA pRgnData = (PRGNDATA)malloc(sizeof(RGNDATAHEADER) + (cRect)*sizeof(RECT)); + memset(pRgnData, 0, sizeof(RGNDATAHEADER)); + pRgnData->rdh.dwSize = sizeof(RGNDATAHEADER); + pRgnData->rdh.iType = RDH_RECTANGLES; + + for (y = 0; y < g_pCachedWindow->Height; ++y) + { + bool inside = false; + bool lastin = false; + unsigned int entry = 0; + + for (x = 0; x < g_pCachedWindow->Width; ++x) + { + inside = Opaque ? (buf->rgbReserved > Level) : (buf->rgbReserved < Level); + ++buf; + + if (inside != lastin) + { + if (inside) + { + lastin = true; + entry = x; + } else { + if (pRgnData->rdh.nCount == cRect) + { + cRect = cRect + 64; + pRgnData = (PRGNDATA)realloc(pRgnData, sizeof(RGNDATAHEADER) + (cRect)*sizeof(RECT)); + } + SetRect(((LPRECT)pRgnData->Buffer) + pRgnData->rdh.nCount, entry, g_pCachedWindow->Height - y, x, g_pCachedWindow->Height - y + 1); + + pRgnData->rdh.nCount++; + lastin = false; + } + } + } + + if (lastin) + { + if (pRgnData->rdh.nCount == cRect) + { + cRect = cRect + 64; + pRgnData = (PRGNDATA)realloc(pRgnData, sizeof(RGNDATAHEADER) + (cRect)*sizeof(RECT)); + } + SetRect(((LPRECT)pRgnData->Buffer) + pRgnData->rdh.nCount, entry, g_pCachedWindow->Height - y, x, g_pCachedWindow->Height - y + 1); + + pRgnData->rdh.nCount++; + } + } + HRGN hRgn = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount*sizeof(RECT), (LPRGNDATA)pRgnData); + free(pRgnData); + + return hRgn; +} + +static int ske_DrawSkinObject(SKINDRAWREQUEST * preq, GLYPHOBJECT * pobj) +{ + HDC memdc=NULL, glyphdc=NULL; + int k=0; + //BITMAP bmp={0}; + HBITMAP membmp=0,oldbmp=0,oldglyph=0; + BYTE Is32Bit=0; + RECT PRect; + POINT mode2offset={0}; + int depth=0; + int mode=0; //0-FastDraw, 1-DirectAlphaDraw, 2-BufferedAlphaDraw + + if (!(preq && pobj)) return -1; + if ((!pobj->hGlyph || pobj->hGlyph==(HBITMAP)-1) && ((pobj->Style&7) ==ST_IMAGE ||(pobj->Style&7) ==ST_FRAGMENT|| (pobj->Style&7) ==ST_SOLARIZE)) return 0; + // Determine painting mode + depth=GetDeviceCaps(preq->hDC,BITSPIXEL); + depth=depth<16?16:depth; + Is32Bit=pobj->bmBitsPixel==32; + if ((!Is32Bit && pobj->dwAlpha==255)&& pobj->Style!=ST_BRUSH) mode=0; + else if (pobj->dwAlpha==255 && pobj->Style!=ST_BRUSH) mode=1; + else mode=2; + // End painting mode + + //force mode + + if(preq->rcClipRect.bottom-preq->rcClipRect.top*preq->rcClipRect.right-preq->rcClipRect.left==0) + preq->rcClipRect=preq->rcDestRect; + IntersectRect(&PRect,&preq->rcDestRect,&preq->rcClipRect); + if (IsRectEmpty(&PRect)) + { + return 0; + } + if (mode==2) + { + memdc=CreateCompatibleDC(preq->hDC); + membmp=ske_CreateDIB32(PRect.right-PRect.left,PRect.bottom-PRect.top); + oldbmp=(HBITMAP)SelectObject(memdc,membmp); + if (oldbmp==NULL) + { + if (mode==2) + { + SelectObject(memdc,oldbmp); + mod_DeleteDC(memdc); + DeleteObject(membmp); + } + return 0; + } + } + + if (mode!=2) memdc=preq->hDC; + { + if (pobj->hGlyph && pobj->hGlyph!=(HBITMAP)-1) + { + glyphdc=CreateCompatibleDC(preq->hDC); + if (!oldglyph) + oldglyph=(HBITMAP)SelectObject(glyphdc,pobj->hGlyph); + else + SelectObject(glyphdc,pobj->hGlyph); + } + // Drawing + { + RECT rFill, rGlyph, rClip; + if ((pobj->Style&7) ==ST_BRUSH) + { + HBRUSH br=CreateSolidBrush(pobj->dwColor); + RECT fr; + if (mode==2) + { + SetRect(&fr,0,0,PRect.right-PRect.left,PRect.bottom-PRect.top); + FillRect(memdc,&fr,br); + ske_SetRectOpaque(memdc,&fr); + // FillRectAlpha(memdc,&fr,pobj->dwColor|0xFF000000); + } + else + { + fr=PRect; + // SetRect(&fr,0,0,PRect.right-PRect.left,PRect.bottom-PRect.top); + FillRect(preq->hDC,&fr,br); + } + DeleteObject(br); + k=-1; + } + else + { + if (mode==2) + { + mode2offset.x=PRect.left; + mode2offset.y=PRect.top; + OffsetRect(&PRect,-mode2offset.x,-mode2offset.y); + } + rClip=(preq->rcClipRect); + + { + int lft=0; + int top=0; + int rgh=pobj->bmWidth; + int btm=pobj->bmHeight; + if ((pobj->Style&7) ==ST_FRAGMENT) + { + lft=pobj->clipArea.x; + top=pobj->clipArea.y; + rgh=min(rgh,lft+pobj->szclipArea.cx); + btm=min(btm,top+pobj->szclipArea.cy); + } + + // Draw center... + if (1) + { + rFill.top=preq->rcDestRect.top+pobj->dwTop; + rFill.bottom=preq->rcDestRect.bottom-pobj->dwBottom; + rFill.left=preq->rcDestRect.left+pobj->dwLeft; + rFill.right=preq->rcDestRect.right-pobj->dwRight; + + if (mode==2) + OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); + + rGlyph.top=top+pobj->dwTop; + rGlyph.left=lft+pobj->dwLeft; + rGlyph.right=rgh-pobj->dwRight; + rGlyph.bottom=btm-pobj->dwBottom; + + k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode,mode,depth); + } + + // Draw top side... + if(1) + { + rFill.top=preq->rcDestRect.top; + rFill.bottom=preq->rcDestRect.top+pobj->dwTop; + rFill.left=preq->rcDestRect.left+pobj->dwLeft; + rFill.right=preq->rcDestRect.right-pobj->dwRight; + + if (mode==2) + OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); + + rGlyph.top=top+0; + rGlyph.left=lft+pobj->dwLeft; + rGlyph.right=rgh-pobj->dwRight; + rGlyph.bottom=top+pobj->dwTop; + + k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_HORZ,mode,depth); + } + // Draw bottom side... + if(1) + { + rFill.top=preq->rcDestRect.bottom-pobj->dwBottom; + rFill.bottom=preq->rcDestRect.bottom; + rFill.left=preq->rcDestRect.left+pobj->dwLeft; + rFill.right=preq->rcDestRect.right-pobj->dwRight; + + if (mode==2) + OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); + + + rGlyph.top=btm-pobj->dwBottom; + rGlyph.left=lft+pobj->dwLeft; + rGlyph.right=rgh-pobj->dwRight; + rGlyph.bottom=btm; + + k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_HORZ,mode,depth); + } + // Draw left side... + if(1) + { + rFill.top=preq->rcDestRect.top+pobj->dwTop; + rFill.bottom=preq->rcDestRect.bottom-pobj->dwBottom; + rFill.left=preq->rcDestRect.left; + rFill.right=preq->rcDestRect.left+pobj->dwLeft; + + if (mode==2) + OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); + + + rGlyph.top=top+pobj->dwTop; + rGlyph.left=lft; + rGlyph.right=lft+pobj->dwLeft; + rGlyph.bottom=btm-pobj->dwBottom; + + k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_VERT,mode,depth); + } + + // Draw right side... + if(1) + { + rFill.top=preq->rcDestRect.top+pobj->dwTop; + rFill.bottom=preq->rcDestRect.bottom-pobj->dwBottom; + rFill.left=preq->rcDestRect.right-pobj->dwRight; + rFill.right=preq->rcDestRect.right; + + if (mode==2) + OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); + + + rGlyph.top=top+pobj->dwTop; + rGlyph.left=rgh-pobj->dwRight; + rGlyph.right=rgh; + rGlyph.bottom=btm-pobj->dwBottom; + + k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_VERT,mode,depth); + } + + + // Draw Top-Left corner... + if(1) + { + rFill.top=preq->rcDestRect.top; + rFill.bottom=preq->rcDestRect.top+pobj->dwTop; + rFill.left=preq->rcDestRect.left; + rFill.right=preq->rcDestRect.left+pobj->dwLeft; + + if (mode==2) + OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); + + + rGlyph.top=top; + rGlyph.left=lft; + rGlyph.right=lft+pobj->dwLeft; + rGlyph.bottom=top+pobj->dwTop; + + k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth); + } + // Draw Top-Right corner... + if(1) + { + rFill.top=preq->rcDestRect.top; + rFill.bottom=preq->rcDestRect.top+pobj->dwTop; + rFill.left=preq->rcDestRect.right-pobj->dwRight; + rFill.right=preq->rcDestRect.right; + + if (mode==2) + OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); + + + rGlyph.top=top; + rGlyph.left=rgh-pobj->dwRight; + rGlyph.right=rgh; + rGlyph.bottom=top+pobj->dwTop; + + k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth); + } + + // Draw Bottom-Left corner... + if(1) + { + rFill.top=preq->rcDestRect.bottom-pobj->dwBottom; + rFill.bottom=preq->rcDestRect.bottom; + rFill.left=preq->rcDestRect.left; + rFill.right=preq->rcDestRect.left+pobj->dwLeft; + + + if (mode==2) + OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); + + + rGlyph.left=lft; + rGlyph.right=lft+pobj->dwLeft; + rGlyph.top=btm-pobj->dwBottom; + rGlyph.bottom=btm; + + k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth); + } + // Draw Bottom-Right corner... + if(1) + { + rFill.top=preq->rcDestRect.bottom-pobj->dwBottom; + rFill.bottom=preq->rcDestRect.bottom; + rFill.left=preq->rcDestRect.right-pobj->dwRight; + rFill.right=preq->rcDestRect.right; + + + if (mode==2) + OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); + + rGlyph.left=rgh-pobj->dwRight; + rGlyph.right=rgh; + rGlyph.top=btm-pobj->dwBottom; + rGlyph.bottom=btm; + + k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth); + } + } + + } + + if ((k>0 || k==-1) && mode==2) + { + { + BLENDFUNCTION bf={AC_SRC_OVER, 0, /*(bm.bmBitsPixel==32)?255:*/pobj->dwAlpha, (pobj->bmBitsPixel==32 && pobj->Style!=ST_BRUSH)?AC_SRC_ALPHA:0}; + if (mode==2) + OffsetRect(&PRect,mode2offset.x,mode2offset.y); + ske_AlphaBlend( preq->hDC,PRect.left,PRect.top,PRect.right-PRect.left,PRect.bottom-PRect.top, + memdc,0,0,PRect.right-PRect.left,PRect.bottom-PRect.top,bf); + } + } + } + //free GDI resources + //--++-- + + //free GDI resources + { + + if (oldglyph) SelectObject(glyphdc,oldglyph); + if (glyphdc) mod_DeleteDC(glyphdc); + } + if (mode==2) + { + SelectObject(memdc,oldbmp); + mod_DeleteDC(memdc); + DeleteObject(membmp); + } + + } + if (pobj->plTextList && pobj->plTextList->realCount>0) + { + int i; + HFONT hOldFont; + for (i=0; iplTextList->realCount; i++) + { + GLYPHTEXT * gt=(GLYPHTEXT *)pobj->plTextList->items[i]; + if (!gt->hFont) + { + if (gl_plSkinFonts && gl_plSkinFonts->realCount>0) + { + int j=0; + for (j=0; jrealCount; j++) + { + SKINFONT * sf; + sf=(SKINFONT*)gl_plSkinFonts->items[j]; + if (sf->szFontID && !strcmp(sf->szFontID,gt->szFontID)) + { + gt->hFont=sf->hFont; + break; + } + } + } + if (!gt->hFont) gt->hFont=(HFONT)-1; + } + if (gt->hFont!=(HFONT)-1) + { + RECT rc={0}; + hOldFont=(HFONT)SelectObject(preq->hDC,gt->hFont); + + + + if (gt->RelativeFlags&2) rc.left=preq->rcDestRect.right+gt->iLeft; + else if (gt->RelativeFlags&1) rc.left=((preq->rcDestRect.right-preq->rcDestRect.left)>>1)+gt->iLeft; + else rc.left=preq->rcDestRect.left+gt->iLeft; + + if (gt->RelativeFlags&8) rc.top=preq->rcDestRect.bottom+gt->iTop; + else if (gt->RelativeFlags&4) rc.top=((preq->rcDestRect.bottom-preq->rcDestRect.top)>>1)+gt->iTop; + else rc.top=preq->rcDestRect.top+gt->iTop; + + if (gt->RelativeFlags&32) rc.right=preq->rcDestRect.right+gt->iRight; + else if (gt->RelativeFlags&16) rc.right=((preq->rcDestRect.right-preq->rcDestRect.left)>>1)+gt->iRight; + else rc.right=preq->rcDestRect.left+gt->iRight; + + if (gt->RelativeFlags&128) rc.bottom=preq->rcDestRect.bottom+gt->iBottom; + else if (gt->RelativeFlags&64) rc.bottom=((preq->rcDestRect.bottom-preq->rcDestRect.top)>>1)+gt->iBottom; + else rc.bottom=preq->rcDestRect.top+gt->iBottom; + + ske_AlphaTextOut(preq->hDC, gt->stText, -1, &rc,gt->dwFlags, gt->dwColor); + SelectObject(preq->hDC,hOldFont); + } + } + } + + return 0; +} + + + +int ske_AddDescriptorToSkinObjectList (LPSKINOBJECTDESCRIPTOR lpDescr, SKINOBJECTSLIST* Skin) +{ + SKINOBJECTSLIST *sk; + if (Skin) sk=Skin; else sk=&g_SkinObjectList; + if (!sk) return 0; + if (mir_bool_strcmpi(lpDescr->szObjectID,"_HEADER_")) return 0; + {//check if new object allready presents. + DWORD i=0; + for (i=0; idwObjLPAlocated;i++) + if (!mir_strcmp(sk->pObjects[i].szObjectID,lpDescr->szObjectID)) return 0; + } + if (sk->dwObjLPAlocated+1>sk->dwObjLPReserved) + { // Realocated list to add space for new object + + sk->pObjects=(SKINOBJECTDESCRIPTOR*)mir_realloc(sk->pObjects,sizeof(SKINOBJECTDESCRIPTOR)*(sk->dwObjLPReserved+1)/*alloc step*/); + sk->dwObjLPReserved++; + } + { //filling new objects field + sk->pObjects[sk->dwObjLPAlocated].bType=lpDescr->bType; + sk->pObjects[sk->dwObjLPAlocated].Data=NULL; + sk->pObjects[sk->dwObjLPAlocated].szObjectID=mir_strdup(lpDescr->szObjectID); + // sk->Objects[sk->dwObjLPAlocated].szObjectName=mir_strdup(lpDescr->szObjectName); + if (lpDescr->Data!=NULL) + { //Copy defaults values + switch (lpDescr->bType) + { + case OT_GLYPHOBJECT: + { + GLYPHOBJECT * obdat; + GLYPHOBJECT * gl=(GLYPHOBJECT*)lpDescr->Data; + sk->pObjects[sk->dwObjLPAlocated].Data=mir_alloc(sizeof(GLYPHOBJECT)); + obdat=(GLYPHOBJECT*)sk->pObjects[sk->dwObjLPAlocated].Data; + memmove(obdat,gl,sizeof(GLYPHOBJECT)); + if (gl->szFileName!=NULL) + { + obdat->szFileName=mir_strdup(gl->szFileName); + mir_free_and_nill(gl->szFileName); + } + else + obdat->szFileName=NULL; + obdat->hGlyph=NULL; + break; + } + } + + } + } + sk->dwObjLPAlocated++; + return 1; +} + +static LPSKINOBJECTDESCRIPTOR ske_FindObject(const char * szName, BYTE objType, SKINOBJECTSLIST* Skin) +{ + // DWORD i; + SKINOBJECTSLIST* sk; + sk=(Skin==NULL)?(&g_SkinObjectList):Skin; + return skin_FindObjectByRequest((char *)szName,sk->pMaskList); +} + +static LPSKINOBJECTDESCRIPTOR ske_FindObjectByMask(MODERNMASK * pModernMask, BYTE objType, SKINOBJECTSLIST* Skin) +{ + // DWORD i; + SKINOBJECTSLIST* sk; + sk=(Skin==NULL)?(&g_SkinObjectList):Skin; + if (!sk->pMaskList) return NULL; + return skin_FindObjectByMask(pModernMask,sk->pMaskList); +} + +LPSKINOBJECTDESCRIPTOR ske_FindObjectByName(const char * szName, BYTE objType, SKINOBJECTSLIST* Skin) +{ + DWORD i; + SKINOBJECTSLIST* sk; + sk=(Skin==NULL)?(&g_SkinObjectList):Skin; + for (i=0; idwObjLPAlocated; i++) + { + if (sk->pObjects[i].bType==objType || objType==OT_ANY) + { + if (!mir_strcmp(sk->pObjects[i].szObjectID,szName)) + return &(sk->pObjects[i]); + } + } + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +// Paint glyph +// wParam - LPSKINDRAWREQUEST +// lParam - possible direct pointer to modern mask +////////////////////////////////////////////////////////////////////////// + +INT_PTR ske_Service_DrawGlyph(WPARAM wParam,LPARAM lParam) +{ + LPSKINDRAWREQUEST preq; + LPSKINOBJECTDESCRIPTOR pgl; + LPGLYPHOBJECT gl; + if (!wParam) return -1; + ske_LockSkin(); + __try + { + preq=(LPSKINDRAWREQUEST)wParam; + if (lParam) + pgl=ske_FindObjectByMask((MODERNMASK*)lParam, OT_GLYPHOBJECT,NULL); + else + pgl=ske_FindObject(preq->szObjectID, OT_GLYPHOBJECT,NULL); + if (pgl==NULL) return -1; + if (pgl->Data==NULL) return -1; + gl= (LPGLYPHOBJECT)pgl->Data; + if ((gl->Style&7) ==ST_SKIP) return ST_SKIP; + if (gl->hGlyph==NULL && gl->hGlyph!=(HBITMAP)-1 && + ( (gl->Style&7)==ST_IMAGE + ||(gl->Style&7)==ST_FRAGMENT + ||(gl->Style&7)==ST_SOLARIZE ) ) + if (gl->szFileName) + { + gl->hGlyph=ske_LoadGlyphImage(gl->szFileName); + if (gl->hGlyph) + { + BITMAP bmp={0}; + GetObject(gl->hGlyph,sizeof(BITMAP),&bmp); + gl->bmBitsPixel=(BYTE)bmp.bmBitsPixel; + gl->bmHeight=bmp.bmHeight; + gl->bmWidth=bmp.bmWidth; + } + else + gl->hGlyph=(HBITMAP)-1; //invalid + } + return ske_DrawSkinObject(preq,gl); + } + __finally + { + ske_UnlockSkin(); + } + return -1; +} + + +void ske_PreMultiplyChanells(HBITMAP hbmp,BYTE Mult) +{ + BITMAP bmp; + BOOL flag=FALSE; + BYTE * pBitmapBits; + DWORD Len; + int bh,bw,y,x; + + GetObject(hbmp, sizeof(BITMAP), (LPSTR)&bmp); + bh=bmp.bmHeight; + bw=bmp.bmWidth; + Len=bh*bw*4; + flag=(bmp.bmBits==NULL); + if (flag) + { + pBitmapBits=(LPBYTE)malloc(Len); + GetBitmapBits(hbmp,Len,pBitmapBits); + } + else + pBitmapBits=(BYTE*)bmp.bmBits; + for (y=0; ybufSize) break; + if (from) if (fromCountsizeof(header)) + { + tga_header_t * header=(tga_header_t *)mem; + if (header->pixel_depth==32&& (header->image_type==2 ||header->image_type==10)) + { + colormap=(BYTE*)malloc(header->width*header->height*4); + cx=header->width; + cy=header->height; + ske_ReadTGAImageData((void*)(mem+sizeof(tga_header_t)+header->id_lenght+header->cm_length), size-(sizeof(tga_header_t)+header->id_lenght+header->cm_length), colormap, cx*cy*4,header->image_type==10); + } + } + FreeResource(hRes); + } + if (colormap) //create dib section + { + BYTE * pt; + HBITMAP hbmp=ske_CreateDIB32Point(cx,cy,(void**)&pt); + if (hbmp) memcpy(pt,colormap,cx*cy*4); + free(colormap); + return hbmp; + } + return NULL; +} + + +//this function is required to load PNG to dib buffer myself +HBITMAP ske_LoadGlyphImage_Png2Dib(char * szFilename) +{ + + { + HANDLE hFile, hMap = NULL; + BYTE* ppMap = NULL; + long cbFileSize = 0; + BITMAPINFOHEADER* pDib; + BYTE* pDibBits; + + if ( !ServiceExists( MS_PNG2DIB )) { + MessageBox( NULL, TranslateT( "You need an image services plugin to process PNG images." ), TranslateT( "Error" ), MB_OK ); + return (HBITMAP)NULL; + } + + if (( hFile = CreateFileA( szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL )) != INVALID_HANDLE_VALUE ) + if (( hMap = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL )) != NULL ) + if (( ppMap = ( BYTE* )MapViewOfFile( hMap, FILE_MAP_READ, 0, 0, 0 )) != NULL ) + cbFileSize = GetFileSize( hFile, NULL ); + + if ( cbFileSize != 0 ) { + PNG2DIB param; + param.pSource = ppMap; + param.cbSourceSize = cbFileSize; + param.pResult = &pDib; + if ( CallService( MS_PNG2DIB, 0, ( LPARAM )¶m )) + pDibBits = ( BYTE* )( pDib+1 ); + else + cbFileSize = 0; + } + + if ( ppMap != NULL ) UnmapViewOfFile( ppMap ); + if ( hMap != NULL ) CloseHandle( hMap ); + if ( hFile != NULL ) CloseHandle( hFile ); + + if ( cbFileSize == 0 ) + return (HBITMAP)NULL; + + { + BITMAPINFO* bi=( BITMAPINFO* )pDib; + BYTE *pt=(BYTE*)bi; + pt+=bi->bmiHeader.biSize; + if (bi->bmiHeader.biBitCount!=32) + { + HDC sDC = GetDC( NULL ); + HBITMAP hBitmap = CreateDIBitmap( sDC, pDib, CBM_INIT, pDibBits, bi, DIB_PAL_COLORS ); + SelectObject( sDC, hBitmap ); + DeleteDC( sDC ); + GlobalFree( pDib ); + return hBitmap; + } + else + { + BYTE * ptPixels=pt; + HBITMAP hBitmap=CreateDIBSection(NULL,bi, DIB_RGB_COLORS, (void **)&ptPixels, NULL, 0); + memcpy(ptPixels,pt,bi->bmiHeader.biSizeImage); + GlobalFree( pDib ); + return hBitmap; + } + } + } +} + +static HBITMAP ske_LoadGlyphImageByDecoders(char * szFileName) +{ + // Loading image from file by imgdecoder... + HBITMAP hBitmap=NULL; + char ext[5]; + BYTE f=0; + LPBYTE pBitmapBits; + LPVOID pImg= NULL; + LPVOID m_pImgDecoder; + + BITMAP bmpInfo; + { + int l; + l=mir_strlen(szFileName); + memmove(ext,szFileName +(l-4),5); + } + if (!strchr(szFileName,'%') && !PathFileExistsA(szFileName)) return NULL; + if (mir_bool_strcmpi(ext,".tga")) + { + hBitmap=ske_LoadGlyphImage_TGA(szFileName); + f=1; + } + else if (ServiceExists("Image/Png2Dib") && mir_bool_strcmpi(ext,".png")) + { + hBitmap=ske_LoadGlyphImage_Png2Dib(szFileName); + GetObject(hBitmap, sizeof(BITMAP), &bmpInfo); + f=(bmpInfo.bmBits!=NULL); + // hBitmap=(HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)szFileName); + // f=1; + + } + else if (hImageDecoderModule==NULL || !mir_bool_strcmpi(ext,".png")) + hBitmap=(HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)szFileName); + else + { + f=1; + ImgNewDecoder(&m_pImgDecoder); + if (!ImgNewDIBFromFile(m_pImgDecoder, szFileName, &pImg)) + { + ImgGetHandle(pImg, &hBitmap, (LPVOID *)&pBitmapBits); + ImgDeleteDecoder(m_pImgDecoder); + } + } + if (hBitmap) + { + + GetObject(hBitmap, sizeof(BITMAP), &bmpInfo); + if (bmpInfo.bmBitsPixel == 32) + ske_PreMultiplyChanells(hBitmap,f); + else + { + HDC dc24,dc32; + HBITMAP hBitmap32,obmp24,obmp32; + dc32=CreateCompatibleDC(NULL); + dc24=CreateCompatibleDC(NULL); + hBitmap32=ske_CreateDIB32(bmpInfo.bmWidth,bmpInfo.bmHeight); + obmp24=(HBITMAP)SelectObject(dc24,hBitmap); + obmp32=(HBITMAP)SelectObject(dc32,hBitmap32); + BitBlt(dc32,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,dc24,0,0,SRCCOPY); + SelectObject(dc24,obmp24); + SelectObject(dc32,obmp32); + mod_DeleteDC(dc24); + mod_DeleteDC(dc32); + DeleteObject(hBitmap); + hBitmap=hBitmap32; + ske_PreMultiplyChanells(hBitmap,0); + } + + } + return hBitmap; +} + +HBITMAP ske_LoadGlyphImage(char * szFileName) +{ + // try to find image in loaded + DWORD i; + HBITMAP hbmp; + char szFile [MAX_PATH]={0}; + ske_GetFullFilename(szFile,szFileName,g_SkinObjectList.szSkinPlace,TRUE); + ske_LockSkin(); + if (pLoadedImages) + { + for (i=0; idwLoadedImagesAlocated) + { + pLoadedImages=(GLYPHIMAGE*)mir_realloc(pLoadedImages,sizeof(GLYPHIMAGE)*(dwLoadedImagesCount+1)); + if (pLoadedImages) dwLoadedImagesAlocated++; + else + { + ske_UnlockSkin(); + return NULL; + } + } + pLoadedImages[dwLoadedImagesCount].dwLoadedTimes=1; + pLoadedImages[dwLoadedImagesCount].hGlyph=hbmp; + pLoadedImages[dwLoadedImagesCount].szFileName=mir_strdup(szFile); + dwLoadedImagesCount++; + ske_UnlockSkin(); + return hbmp; +} +int ske_UnloadGlyphImage(HBITMAP hbmp) +{ + DWORD i; + for (i=0; iszFileName) mir_free_and_nill(gl->szFileName); + memmove(&(pLoadedImages[i]),&(pLoadedImages[i+1]),sizeof(GLYPHIMAGE)*(dwLoadedImagesCount-i-1)); + dwLoadedImagesCount--; + DeleteObject(hbmp); + if (pLoadedImages && dwLoadedImagesCount==0) + { + dwLoadedImagesAlocated=0; + mir_free_and_nill(pLoadedImages); + } + } + return 0; + } + + } + DeleteObject(hbmp); + return 0; +} + +int ske_UnloadSkin(SKINOBJECTSLIST * Skin) +{ + + DWORD i; + ske_LockSkin(); + ClearMaskList(Skin->pMaskList); + {//clear font list + int i; + if (gl_plSkinFonts && gl_plSkinFonts->realCount>0) + { + for (i=0; irealCount; i++) + { + SKINFONT * sf=(SKINFONT *)gl_plSkinFonts->items[i]; + if (sf) + { + if (sf->szFontID) mir_free_and_nill(sf->szFontID); + DeleteObject(sf->hFont); + mir_free_and_nill(sf); + } + } + li.List_Destroy(gl_plSkinFonts); + mir_free_and_nill(gl_plSkinFonts); + } + } + + if (Skin->szSkinPlace) mir_free_and_nill(Skin->szSkinPlace); + if (Skin->pTextList) li.List_Destroy(Skin->pTextList); + mir_free_and_nill(Skin->pTextList); + ModernSkinButtonDeleteAll(); + if (Skin->dwObjLPAlocated==0) { ske_UnlockSkin(); return 0;} + for (i=0; idwObjLPAlocated; i++) + { + switch(Skin->pObjects[i].bType) + { + case OT_GLYPHOBJECT: + { + GLYPHOBJECT * dt; + dt=(GLYPHOBJECT*)Skin->pObjects[i].Data; + if (dt->hGlyph && dt->hGlyph!=(HBITMAP)-1) + ske_UnloadGlyphImage(dt->hGlyph); + dt->hGlyph=NULL; + if (dt->szFileName) mir_free_and_nill(dt->szFileName); + {// delete texts + int i; + if (dt->plTextList && dt->plTextList->realCount>0) + { + for (i=0; iplTextList->realCount; i++) + { + GLYPHTEXT * gt=(GLYPHTEXT *)dt->plTextList->items[i]; + if (gt) + { + if (gt->stText) mir_free_and_nill(gt->stText); + if (gt->stValueText) mir_free_and_nill(gt->stValueText); + if (gt->szFontID) mir_free_and_nill(gt->szFontID); + if (gt->szGlyphTextID)mir_free_and_nill(gt->szGlyphTextID); + mir_free_and_nill(gt); + } + } + li.List_Destroy(dt->plTextList); + mir_free_and_nill(dt->plTextList); + } + } + mir_free_and_nill(dt); + } + break; + } + if (Skin->pObjects[i].szObjectID) mir_free_and_nill(Skin->pObjects[i].szObjectID); + + } + mir_free_and_nill(Skin->pObjects); + Skin->pTextList=NULL; + Skin->dwObjLPAlocated=0; + Skin->dwObjLPReserved=0; + ske_UnlockSkin(); + return 0; +} + +static void RegisterMaskByParce(const char * szSetting, char * szValue, SKINOBJECTSLIST * pSkin) +{ + int i; + DWORD ID=atoi(szSetting+1); + for (i=0; ipMaskList,pSkin); + mir_free_and_nill(Obj); + } +} + +static int ske_ProcessLoadindString(const char * szSetting, char *szValue) +{ + if (!pCurrentSkin) return 0; + if (szSetting[0]=='$') + RegisterObjectByParce((char *)szSetting, szValue); + else if (szSetting[0]=='#') + RegisterButtonByParce((char *)szSetting,szValue); + else if (szSetting[0]=='@') + RegisterMaskByParce((char *)szSetting, szValue, pCurrentSkin); /// + else if (szSetting[0]=='t') + ske_AddParseTextGlyphObject((char*)szSetting,szValue,pCurrentSkin); + else if (szSetting[0]=='f') + ske_AddParseSkinFont((char*)szSetting,szValue,pCurrentSkin); + else return 0; + return 1; +} +static int ske_enumdb_SkinObjectsProc (const char *szSetting,LPARAM lParam) +{ + char *value; + value= ModernGetStringA(NULL,SKIN,szSetting); + ske_ProcessLoadindString(szSetting,value); + mir_free_and_nill(value); + + return 0; +} + +static int ske_SortTextGlyphObjectFunc(void * first, void * second) +{ + return strcmp(((GLYPHTEXT*)(((int*)first)[0]))->szGlyphTextID,((GLYPHTEXT*)(((int*)second)[0]))->szGlyphTextID); +} + +static void ske_LinkSkinObjects(SKINOBJECTSLIST * pObjectList) +{ + DWORD i; + // LINK Mask with objects + for (i=0; ipMaskList->dwMaskCnt; i++) + { + MODERNMASK *mm=&(pObjectList->pMaskList->pl_Masks[i]); + void * pObject=(void*) ske_FindObjectByName(mm->szObjectName, OT_ANY, (SKINOBJECTSLIST*) pObjectList); + mir_free_and_nill(mm->szObjectName); + mm->bObjectFound=TRUE; + mm->pObject=pObject; + } + + if (pObjectList->pTextList) + { + int i; + // LINK Text with objects + for (i=0; ipTextList->realCount; i++) + { + GLYPHTEXT * glText; + GLYPHOBJECT *globj=NULL; + SKINOBJECTDESCRIPTOR * lpobj; + glText=(GLYPHTEXT *)pObjectList->pTextList->items[i]; + lpobj=ske_FindObjectByName(glText->szObjectName,OT_GLYPHOBJECT, pObjectList); + mir_free_and_nill(glText->szObjectName); + if (lpobj) + globj=(GLYPHOBJECT*)lpobj->Data; + if (globj) + { + if (!globj->plTextList) + { + globj->plTextList=li.List_Create(0,1); + globj->plTextList->sortFunc=ske_SortTextGlyphObjectFunc; + } + li.List_Insert(globj->plTextList,(void*)glText,globj->plTextList->realCount); + qsort(globj->plTextList->items,globj->plTextList->realCount,sizeof(void*),(int(*)(const void*, const void*))globj->plTextList->sortFunc); + pObjectList->pTextList->items[i]=NULL; + } + else + { + GLYPHTEXT * gt=glText; + if (gt) + { + if (gt->stText) mir_free_and_nill(gt->stText); + if (gt->stValueText) mir_free_and_nill(gt->stValueText); + if (gt->szFontID) mir_free_and_nill(gt->szFontID); + if (gt->szGlyphTextID)mir_free_and_nill(gt->szGlyphTextID); + mir_free_and_nill(gt); + } + } + } + li.List_Destroy(pObjectList->pTextList); + mir_free_and_nill(pObjectList->pTextList); + } +} +// Getting skin objects and masks from DB +static int ske_GetSkinFromDB(char * szSection, SKINOBJECTSLIST * Skin) +{ + if (Skin==NULL) return 0; + ske_UnloadSkin(Skin); + g_CluiData.fDisableSkinEngine=ModernGetSettingByte(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT); + //window borders + if (g_CluiData.fDisableSkinEngine) { + g_CluiData.LeftClientMargin=0; + g_CluiData.RightClientMargin=0; + g_CluiData.TopClientMargin=0; + g_CluiData.BottomClientMargin=0; + } else { + //window borders + g_CluiData.LeftClientMargin=(int)ModernGetSettingByte(NULL,"CLUI","LeftClientMargin",SETTING_LEFTCLIENTMARIGN_DEFAULT); + g_CluiData.RightClientMargin=(int)ModernGetSettingByte(NULL,"CLUI","RightClientMargin",SETTING_RIGHTCLIENTMARIGN_DEFAULT); + g_CluiData.TopClientMargin=(int)ModernGetSettingByte(NULL,"CLUI","TopClientMargin",SETTING_TOPCLIENTMARIGN_DEFAULT); + g_CluiData.BottomClientMargin=(int)ModernGetSettingByte(NULL,"CLUI","BottomClientMargin",SETTING_BOTTOMCLIENTMARIGN_DEFAULT); + } + + if (g_CluiData.fDisableSkinEngine) return 0; + + Skin->pMaskList=(LISTMODERNMASK*)mir_alloc(sizeof(LISTMODERNMASK)); + memset(Skin->pMaskList,0,sizeof(LISTMODERNMASK)); + Skin->szSkinPlace= ModernGetStringA(NULL,SKIN,"SkinFolder"); + if (!Skin->szSkinPlace || (strchr(Skin->szSkinPlace, '%') && !ModernGetSettingByte(NULL,SKIN,"Modified",0)) ) + { + BOOL bOnlyObjects=FALSE; + if (Skin->szSkinPlace && strchr(Skin->szSkinPlace, '%')) + bOnlyObjects=TRUE; + mir_free(Skin->szSkinPlace); + Skin->szSkinPlace=mir_strdup("%Default%"); + ske_LoadSkinFromResource( bOnlyObjects ); + } + //Load objects + { + DBCONTACTENUMSETTINGS dbces; + pCurrentSkin=Skin; + dbces.pfnEnumProc=ske_enumdb_SkinObjectsProc; + dbces.szModule=SKIN; + dbces.ofsSettings=0; + CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces); + + SortMaskList(pCurrentSkin->pMaskList); + ske_LinkSkinObjects(pCurrentSkin); + } + //Load Masks + return 0; +} + +//surrogate to be called from outside +void ske_LoadSkinFromDB(void) +{ + ske_GetSkinFromDB(SKIN,&g_SkinObjectList); + g_CluiData.dwKeyColor=ModernGetSettingDword(NULL,"ModernSettings","KeyColor",(DWORD)SETTING_KEYCOLOR_DEFAULT); +} + + + +// + + +/* +static BOOL ske_ParseLineOfIniFile(char * Line, BOOL bOnlyObjects) +{ + DWORD i=0; + DWORD len=strlen(Line); + while (i=len) return FALSE; //only spaces (or tabs) + if (len>0 && Line[len-1]==10) Line[len-1]='\0'; + switch(Line[i]) + { + case ';': + return FALSE; // start of comment is found + case '[': + //New section start here + if (iniCurrentSection) mir_free_and_nill(iniCurrentSection); + { + char *tbuf=Line+i+1; + DWORD len2=strlen(tbuf); + DWORD k=len2; + while (k>0 && tbuf[k]!=']') k--; //searching close bracket + tbuf[k]='\0'; //closing string + if (k==0) return FALSE; + iniCurrentSection=mir_strdup(tbuf); + } + return TRUE; + default: + if (!iniCurrentSection) return FALSE; //param found out of section + { + char *keyName=Line+i; + char *keyValue=Line+i; + + DWORD eqPlace=0; + DWORD len2=strlen(keyName); + while (eqPlace0 && (keyName[j]==' ' || keyName[j]=='\t')) j--; + if (j>=0) keyName[j+1]='\0'; + } + //remove start spaces in Value + { + DWORD len3=strlen(keyValue); + DWORD j=0; + while (j0 && (keyValue[j]==' ' || keyValue[j]=='\t')) j--; + if (j>=0) keyValue[j+1]='\0'; + } + ske_WriteParamToDatabase(iniCurrentSection,keyName,keyValue,TRUE); + } + } + return FALSE; +} +*/ +//Load data from ini file + + + +//int ske_OldLoadSkinFromIniFile(char * szFileName) +//{ +// char bsn[MAXSN_BUFF_SIZE]; +// char * Buff; +// +// int i=0; +// int f=0; +// int ReadingSection=0; +// char AllowedSection[260]; +// int AllowedAll=0; +// char t2[MAX_PATH]; +// char t3[MAX_PATH]; +// +// DWORD retu=GetPrivateProfileSectionNamesA(bsn,MAXSN_BUFF_SIZE,szFileName); +// ske_DeleteAllSettingInSection("ModernSkin"); +// ske_GetSkinFolder(szFileName,t2); +// ModernWriteSettingString(NULL,SKIN,"SkinFolder",t2); +// CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)szFileName, (LPARAM)t3); +// ModernWriteSettingString(NULL,SKIN,"SkinFile",t3); +// Buff=bsn; +// AllowedSection[0]=0; +// do +// { +// f=mir_strlen(Buff); +// if (f>0 && !mir_bool_strcmpi(Buff,"Skin_Description_Section")) +// { +// char b3[MAX_BUFF_SIZE]; +// DWORD ret=0; +// ret=GetPrivateProfileSectionA(Buff,b3,MAX_BUFF_SIZE,szFileName); +// if (ret>MAX_BUFF_SIZE-3) continue; +// if (ret==0) continue; +// { +// DWORD p=0; +// char *s1; +// char *s2; +// char *s3; +// { +// DWORD t; +// BOOL LOCK=FALSE; +// for (t=0; tMAXPREDEFINEDEFFECTS) return; + if (EffectID==-1) meCurrentEffect.EffectID=-1; + else + { + meCurrentEffect.EffectID=EffectID; + meCurrentEffect.EffectMatrix=ModernEffectsEnum[EffectID]; + meCurrentEffect.EffectColor1=FirstColor; + meCurrentEffect.EffectColor2=SecondColor; + } +} + +BOOL ske_ResetTextEffect(HDC hdc) +{ + int i; + if (!pEffectStack || !pEffectStack->realCount) return TRUE; + for (i=0; irealCount; i++) + if (pEffectStack->items[i] && ((EFFECTSSTACKITEM*)(pEffectStack->items[i]))->hdc==hdc) + { + EFFECTSSTACKITEM * effect=(EFFECTSSTACKITEM*)(pEffectStack->items[i]); + mir_free_and_nill(effect); + li.List_Remove(pEffectStack,i); + return TRUE; + } + return FALSE; +}; + +BOOL ske_SelectTextEffect(HDC hdc, BYTE EffectID, DWORD FirstColor, DWORD SecondColor) +{ + if (EffectID>MAXPREDEFINEDEFFECTS) return 0; + if (EffectID==-1) return ske_ResetTextEffect(hdc); + if (!pEffectStack) + { + pEffectStack=li.List_Create(0,1); + } + { + int i; + for (i=0; irealCount; i++) + if (pEffectStack->items[i] && ((EFFECTSSTACKITEM*)(pEffectStack->items[i]))->hdc==hdc) + { + EFFECTSSTACKITEM * effect=(EFFECTSSTACKITEM*)(pEffectStack->items[i]); + effect->EffectID=EffectID; + effect->FirstColor=FirstColor; + effect->SecondColor=SecondColor; + return TRUE; + } + } + { + EFFECTSSTACKITEM * effect=(EFFECTSSTACKITEM *) mir_alloc(sizeof(EFFECTSSTACKITEM)); + effect->hdc=hdc; + effect->EffectID=EffectID; + effect->FirstColor=FirstColor; + effect->SecondColor=SecondColor; + li.List_Insert(pEffectStack, effect, 0); + return TRUE; + } + return FALSE; +} + +static BOOL ske_GetTextEffect(HDC hdc, MODERNEFFECT * modernEffect) +{ + int i=0; + if (!pEffectStack || !pEffectStack->realCount) return FALSE; + if (!modernEffect) return FALSE; + for (i=0; irealCount; i++) + if (pEffectStack->items[i] && ((EFFECTSSTACKITEM*)(pEffectStack->items[i]))->hdc==hdc) + { + EFFECTSSTACKITEM * effect=(EFFECTSSTACKITEM*)(pEffectStack->items[i]); + modernEffect->EffectID=effect->EffectID; + modernEffect->EffectColor1=effect->FirstColor; + modernEffect->EffectColor2=effect->SecondColor; + modernEffect->EffectMatrix=ModernEffectsEnum[effect->EffectID]; + return TRUE; + } + return FALSE; +} + +static BOOL ske_DrawTextEffect(BYTE* destPt,BYTE* maskPt, DWORD width, DWORD height, MODERNEFFECT *effect) +{ + sbyte *buf; + sbyte *outbuf; + sbyte *bufline, *buflineTop, *buflineMid; + int sign=0; + BYTE *maskline,*destline; + BYTE al,rl,gl,bl,ad,rd,gd,bd; + int k=0; + DWORD x,y; + sbyte *matrix; + BYTE mcTopStart; + BYTE mcBottomEnd; + BYTE mcLeftStart; + BYTE mcRightEnd; + BYTE effectCount; + int minX=width; + int maxX=0; + int minY=height; + int maxY=0; + if (effect->EffectID==0xFF) return FALSE; + if (!width || ! height) return FALSE; + if (!destPt) return FALSE; + buf=(sbyte*)malloc(width*height*sizeof(BYTE)); + { + matrix=effect->EffectMatrix.matrix; + mcTopStart=2-effect->EffectMatrix.topEffect; + mcBottomEnd=3+effect->EffectMatrix.bottomEffect; + mcLeftStart=2-effect->EffectMatrix.leftEffect; + mcRightEnd=3+effect->EffectMatrix.rightEffect; + effectCount=effect->EffectMatrix.cycleCount; + } + al=255-((BYTE)(effect->EffectColor1>>24)); + rl=GetRValue(effect->EffectColor1); + gl=GetGValue(effect->EffectColor1); + bl=GetBValue(effect->EffectColor1); + rd=GetRValue(effect->EffectColor2); + gd=GetGValue(effect->EffectColor2); + bd=GetBValue(effect->EffectColor2); + ad=255-((BYTE)(effect->EffectColor2>>24)); + rd=GetRValue(effect->EffectColor2); + gd=GetGValue(effect->EffectColor2); + bd=GetBValue(effect->EffectColor2); + + //Fill buffer by mid values of image + for (y=0; y>4); + *bufline=a; + if (a!=0) + { + minX=min((int)x,minX); + minY=min((int)y,minY); + maxX=max((int)x,maxX); + maxY=max((int)y,maxY); + } + bufline++; + maskline+=4; + } + } + //Here perform effect on buffer and place results to outbuf + for (k=0; k<(effectCount&0x7F); k++) + { + minX = max( 0, minX + mcLeftStart - 2 ); + minY = max( 0, minY + mcTopStart - 2 ); + maxX = min( (int)width, maxX + mcRightEnd - 1 ); + maxY = min( (int)height, maxY + mcBottomEnd - 1 ); + + outbuf=(sbyte*)malloc(width*height*sizeof(sbyte)); + memset(outbuf,0,width*height*sizeof(sbyte)); + for (y=(DWORD)minY; y<(DWORD)maxY; y++) + { + int val; + bufline=outbuf+y*width+minX; + buflineMid=buf+y*width+minX; + for (x=(DWORD)minX; x<(DWORD)maxX; x++) + { + int matrixHor,matrixVer; + val=0; + for (matrixVer=mcTopStart; matrixVer=0 && (DWORD)as=0 && (DWORD)a>5; + *bufline=(sbyte)((val>127)?127:(val<-125)?-125:val); + bufline++; + buflineMid++; + } + } + free(buf); + buf=outbuf; + } + { + BYTE r1,b1,g1,a1; + b1=bl; r1=rl; g1=gl; a1=al; sign=1; + //perform out to dest + for (y=0; y0 && sign<0) + { b1=bl; r1=rl; g1=gl; a1=al; sign=1;} + else if (val<0 && sign>0) + { b1=bd; r1=rd; g1=gd; a1=ad; sign=-1;} + + absVal=absVal*a1/255; + + destline[0]=((destline[0]*(128-absVal))+absVal*b1)>>7; + destline[1]=((destline[1]*(128-absVal))+absVal*g1)>>7; + destline[2]=((destline[2]*(128-absVal))+absVal*r1)>>7; + destline[3]+=((255-destline[3])*(a1*absVal))/32640; + } + bufline++; + destline+=4; + } + } + free(buf); + } + return FALSE; +} + +static int ske_AlphaTextOut (HDC hDC, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format, DWORD ARGBcolor) +{ + if( !( lpString && lpRect ) ) + { + DebugBreak(); + return 0; + } + + // Step first fill fast calc correction tables: + static bool _tables_empty = true; + static BYTE gammaTbl[256]; // Gamma correction table + static WORD blueMulTbl[256]; // blue coefficient multiplication table + static WORD greenMulTbl[256]; // green coefficient multiplication table + static WORD redMulTbl[256]; // red coefficient multiplication table + if ( _tables_empty ) + { + // fill tables + double gammaCfPw = 1000 / (double)ModernGetSettingRangedWord(NULL,"ModernData","AlphaTextOutGamma", 700, 1, 5000 ); + BYTE blueCf = ModernGetSettingByte(NULL,"ModernData","AlphaTextOutBlueCorrection", 28 ); + BYTE redCf = ModernGetSettingByte(NULL,"ModernData","AlphaTextOutRed Correction", 77 ); + BYTE greenCf = ModernGetSettingByte(NULL,"ModernData","AlphaTextOutGreen Correction", 151 ); + + for( int i = 0; i < 256; i++ ) + { + gammaTbl[i]= (BYTE)( 255 * pow( (double)i / 255, gammaCfPw ) ); + blueMulTbl[i] = i * blueCf; + redMulTbl[i] = i * redCf; + greenMulTbl[i] = i * greenCf; + } + } + + // Calc len of input string + if ( nCount == -1 ) nCount = lstrlen( lpString ); + + // retrieve destination bitmap bits + HBITMAP hDestBitmap = (HBITMAP) GetCurrentObject( hDC, OBJ_BITMAP ); + BITMAP bmpDest; + GetObject( hDestBitmap, sizeof(BITMAP), &bmpDest ); + + BOOL destHasNotDIB = FALSE; + BYTE * pDestBits = NULL; + if ( bmpDest.bmBits == NULL ) + { + destHasNotDIB = TRUE; + pDestBits = (BYTE*) malloc ( bmpDest.bmHeight * bmpDest.bmWidthBytes ); + GetBitmapBits( hDestBitmap, bmpDest.bmHeight*bmpDest.bmWidthBytes, pDestBits ); + } + else + pDestBits=(BYTE*)bmpDest.bmBits; + + BOOL isDest16bit=( bmpDest.bmBitsPixel ) != 32; + + + // Creating offscreen buffer + HDC hOffscreenDC = CreateCompatibleDC( hDC ); + + // Font to be used to draw text + HFONT hFont = (HFONT)GetCurrentObject( hDC, OBJ_FONT); + HFONT hOldOffscreenFont = (HFONT)SelectObject( hOffscreenDC, hFont ); + + // Calculating text geometric size + RECT workRect = *lpRect; + int workRectWidth = workRect.right - workRect.left; + int workRectHeight = workRect.bottom - workRect.top; + + if ( workRectWidth <= 0 || workRectHeight <= 0 ) + return 0; + + SIZE textSize; + GetTextExtentPoint32( hOffscreenDC, lpString, nCount, &textSize ); + + LPCTSTR lpWorkString = lpString; + BOOL bNeedFreeWorkString = FALSE; + + // if we need to cut the text with ellipsis + if ( ( format&DT_END_ELLIPSIS ) && textSize.cx > workRectWidth ) + { + // Calc geometric width of ellipsis + SIZE szEllipsis; + GetTextExtentPoint32A(hOffscreenDC,"...",3,&szEllipsis); + szEllipsis.cx++; // CORRECTION: some width correction + + // Calc count of visible chars + int visibleCharCount = nCount; + if ( workRectWidth > szEllipsis.cx) + { + GetTextExtentExPoint( hOffscreenDC, lpString, nCount, + workRectWidth - szEllipsis.cx, + &visibleCharCount, NULL, &textSize ); + } + else + { + GetTextExtentExPoint( hOffscreenDC, lpString, nCount, + 0, &visibleCharCount, NULL, &textSize); + } + + // replace end of string by elipsis + bNeedFreeWorkString = TRUE; + lpWorkString = (TCHAR*) malloc( ( visibleCharCount + 4) * sizeof(TCHAR) ); + + memcpy( (void*) lpWorkString, lpString, visibleCharCount * sizeof(TCHAR) ); + memcpy( (void*) ( lpWorkString + visibleCharCount ), _T("..."), 4 * sizeof(TCHAR)); // 3 + 1 + + nCount = visibleCharCount + 3; + } + + // Calc sizes and offsets + + textSize.cx += 2; // CORRECTION: for italic + + int drx = 0; // x-axis offset of draw point + + if ( workRectWidth > textSize.cx ) + { + if ( format & ( DT_RIGHT | DT_RTLREADING ) ) + { + drx = workRectWidth - textSize.cx; + } + else if ( format & DT_CENTER ) + { + drx = ( workRectWidth - textSize.cx ) >> 1; + } + } + else + { + textSize.cx = workRectWidth; + } + + int dry = 0; // y-axis offset of draw point + + if ( workRectHeight > textSize.cy ) + { + if ( format & DT_BOTTOM ) + { + dry = workRectHeight - textSize.cy; + } + else if ( format & DT_VCENTER ) + { + dry = ( workRectHeight - textSize.cy ) >> 1; + } + } + else + { + textSize.cy = workRectHeight; + } + + textSize.cx += 4; // CORRECTION: for effects ??? + textSize.cy += 4; // CORRECTION: for effects ??? + + if ( textSize.cx > 0 && textSize.cy > 0 ) // Ok we need to paint + { + // probably here are mess ofscreen and temp buff dc + + //Create bitmap image for offscreen + BYTE * bits = NULL; + HBITMAP hbmp = ske_CreateDIB32Point( textSize.cx, textSize.cy, (void**)&bits ); + if ( bits != NULL ) + { + HBITMAP holdbmp = (HBITMAP)SelectObject( hOffscreenDC, hbmp ); + + //Create buffer bitmap image for temp text + BYTE * bufbits = NULL; + HBITMAP bufbmp = ske_CreateDIB32Point( textSize.cx, textSize.cy, (void**)&bufbits ); + if ( bufbits != NULL ) + { + HDC bufDC = CreateCompatibleDC( hDC ); + HBITMAP bufoldbmp = (HBITMAP)SelectObject( bufDC, bufbmp ); + HFONT hOldBufFont = (HFONT)SelectObject( bufDC, hFont ); + SetBkColor( bufDC, RGB( 0, 0, 0 ) ); + SetTextColor( bufDC,RGB(255,255,255) ); + + // Copy from destination to temp buffer + BitBlt( hOffscreenDC, 0, 0, textSize.cx, textSize.cy, hDC, workRect.left + drx - 2, workRect.top + dry - 2, SRCCOPY ); + + //Draw text on offscreen bitmap + TextOut( bufDC, 2, 2, lpWorkString, nCount); + + MODERNEFFECT effect; + if (ske_GetTextEffect( hDC, &effect ) ) + ske_DrawTextEffect( bits, bufbits, textSize.cx, textSize.cy, &effect ); + + //RenderText + RECT drawRect; + drawRect.left = 0; drawRect.top = 0; + drawRect.right = textSize.cx; + drawRect.bottom = textSize.cy; + + DWORD x,y; + DWORD width=textSize.cx; + DWORD heigh=textSize.cy; + + BYTE * pDestScanLine; + BYTE * pBufScanLine; + BYTE * pix; + BYTE * bufpix; + + BYTE al = 255 - ((BYTE)( ARGBcolor >> 24 )); + BYTE r = GetRValue( ARGBcolor ); + BYTE g = GetGValue( ARGBcolor ); + BYTE b = GetBValue( ARGBcolor ); + + for ( y = 2; y < heigh - 2; y++ ) + { + int lineBytes = y * (width<<2); + + pDestScanLine = bits + lineBytes; + pBufScanLine = bufbits + lineBytes; + + for( x = 2; x < width - 2; x++) + { + pix = pDestScanLine + ( x<<2 ); + bufpix = pBufScanLine + ( x<<2 ); + + // Monochromatic + BYTE bx = gammaTbl[ bufpix[0] ]; + BYTE gx = gammaTbl[ bufpix[1] ]; + BYTE rx = gammaTbl[ bufpix[2] ]; + + if ( al != 255 ) + { + bx*=al/255; + gx*=al/255; + rx*=al/255; + } + BYTE ax = (BYTE)( ( (DWORD)rx*77 + (DWORD)gx * 151 + (DWORD)bx *28 + 128 ) / 256 ); + + if (ax) + { + //Normalize components to gray + BYTE axx = 255 - ( ( r + g + b ) >> 2 ) ; // Coefficient of grayance, more white font - more gray edges + WORD atx = ax * (255 - axx); + bx=( atx + bx * axx )/255; + gx=( atx + gx * axx )/255; + rx=( atx + rx * axx )/255; + + short rrx, grx, brx; + brx=(short)((b-pix[0])*bx/255); + grx=(short)((g-pix[1])*gx/255); + rrx=(short)((r-pix[2])*rx/255); + + pix[0]+=brx; + pix[1]+=grx; + pix[2]+=rrx; + pix[3]=(BYTE)(ax+(BYTE)(255-ax)*pix[3]/255); + } + } + } + + //Blit to destination + BitBlt( hDC, workRect.left + drx - 2, workRect.top + dry - 2, textSize.cx, textSize.cy, hOffscreenDC, 0, 0, SRCCOPY ); + + //free resources + SelectObject(bufDC,bufoldbmp); + DeleteObject(bufbmp); + SelectObject(bufDC, hOldBufFont ); + mod_DeleteDC(bufDC); + } + SelectObject(hOffscreenDC,holdbmp); + DeleteObject(hbmp); + } + } + + // Final cleanup + SelectObject( hOffscreenDC, hOldOffscreenFont ); + DeleteDC( hOffscreenDC ); + + if ( destHasNotDIB ) + free( pDestBits ); + + if ( bNeedFreeWorkString ) + free( (void*)lpWorkString ); + + return 0; +} + +static int ske_DrawTextWithEffectWorker( HDC hdc, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format, MODERNFONTEFFECT * effect ) +{ + if (format&DT_CALCRECT) return DrawText(hdc,lpString,nCount,lpRect,format); + + if (format&DT_RTLREADING) SetTextAlign(hdc,TA_RTLREADING); + DWORD color=GetTextColor(hdc); + + RECT r=*lpRect; + OffsetRect(&r,1,1); + DWORD form = format; + if ( effect && effect->effectIndex ) + ske_SelectTextEffect( hdc, effect->effectIndex - 1, effect->baseColour, effect->secondaryColour ); + + int res = ske_AlphaTextOut(hdc, lpString, nCount, lpRect, form, color ); + + if ( effect && effect->effectIndex ) + ske_ResetTextEffect( hdc ); + + return res; +} + +INT_PTR ske_Service_DrawTextWithEffect( WPARAM wParam, LPARAM lParam ) +{ + DrawTextWithEffectParam * p = ( DrawTextWithEffectParam * ) wParam; + if ( p->cbSize != sizeof(DrawTextWithEffectParam) ) + return FALSE; + return ske_DrawTextWithEffectWorker( p->hdc, p->lpchText, p->cchText, p->lprc, p->dwDTFormat, p->pEffect ); +} + +BOOL ske_DrawTextA(HDC hdc, char * lpString, int nCount, RECT * lpRect, UINT format) +{ +#ifdef UNICODE + TCHAR *buf=mir_a2u(lpString); + BOOL res; + res=ske_DrawText(hdc,buf,nCount,lpRect,format); + mir_free(buf); + return res; +#else + return ske_DrawText(hdc,lpString,nCount,lpRect,format); +#endif +} + + +BOOL ske_DrawText(HDC hdc, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format) +{ + DWORD form=0, color=0; + RECT r=*lpRect; + OffsetRect(&r,1,1); + if (format&DT_RTLREADING) SetTextAlign(hdc,TA_RTLREADING); + if (format&DT_CALCRECT) return DrawText(hdc,lpString,nCount,lpRect,format); + if (format&DT_FORCENATIVERENDER || g_CluiData.fDisableSkinEngine) + return DrawText(hdc,lpString,nCount,lpRect,format&~DT_FORCENATIVERENDER); + form=format; + color=GetTextColor(hdc); + if (!g_CluiData.fGDIPlusFail &&0) ///text via gdi+ + { + TextOutWithGDIp(hdc,lpRect->left,lpRect->top,lpString,nCount); + return 0; + } + return ske_AlphaTextOut(hdc,lpString,nCount,lpRect,form,color); +} + +HICON ske_ImageList_GetIcon(HIMAGELIST himl, int i, UINT fStyle) +{ + IMAGEINFO imi={0}; + BITMAP bm={0}; + if ( IsWinVerXPPlus() && i!=-1 ) + { + ImageList_GetImageInfo(himl,i,&imi); + GetObject(imi.hbmImage,sizeof(bm),&bm); + if (bm.bmBitsPixel==32) //stupid bug of Microsoft + // Icons bitmaps are not premultiplied + // So Imagelist_AddIcon - premultiply alpha + // But incorrect - it is possible that alpha will + // be less than color and + // ImageList_GetIcon will return overflowed colors + // TODO: Direct draw Icon from imagelist without + // extracting of icon + { + BYTE * bits=NULL; + bits=(BYTE*)bm.bmBits; + if (!bits) + { + bits=(BYTE*)malloc(bm.bmWidthBytes*bm.bmHeight); + GetBitmapBits(imi.hbmImage,bm.bmWidthBytes*bm.bmHeight,bits); + } + { + int iy; + BYTE *bcbits; + int wb=((imi.rcImage.right-imi.rcImage.left)*bm.bmBitsPixel>>3); + bcbits=bits+(bm.bmHeight-imi.rcImage.bottom)*bm.bmWidthBytes+(imi.rcImage.left*bm.bmBitsPixel>>3); + for (iy=0; iy>24); + if (a!=0) + { + BYTE r= (BYTE)((val&0xFF0000)>>16); + BYTE g= (BYTE)((val&0xFF00)>>8); + BYTE b= (BYTE)(val&0xFF); + if (ahdc,p->xLeft,p->yTop,p->hIcon,p->cxWidth,p->cyWidth,p->istepIfAniCur,p->hbrFlickerFreeDraw,p->diFlags); +} + + +BOOL ske_DrawIconEx(HDC hdcDst,int xLeft,int yTop,HICON hIcon,int cxWidth,int cyWidth, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags) +{ + + ICONINFO ici; + BYTE alpha=(BYTE)((diFlags&0xFF000000)>>24); + + + HDC imDC; + HBITMAP oldBmp, imBmp,tBmp; + BITMAP imbt,immaskbt; + BYTE * imbits; + BYTE * imimagbits; + BYTE * immaskbits; + DWORD cx,cy,icy; + BYTE *t1, *t2, *t3; + + BOOL NoDIBImage=FALSE; + //lockimagelist + BYTE hasmask=FALSE; + BYTE no32bit=FALSE; + BYTE noMirrorMask=FALSE; + BYTE hasalpha=FALSE; + alpha=alpha?alpha:255; + + if ( g_CluiData.fDisableSkinEngine && !(diFlags&0x80) ) + return DrawIconEx(hdcDst,xLeft,yTop,hIcon,cxWidth,cyWidth,istepIfAniCur,hbrFlickerFreeDraw,diFlags&0xFFFF7F); + + if (!GetIconInfo(hIcon,&ici)) return 0; + + GetObject(ici.hbmColor,sizeof(BITMAP),&imbt); + if (imbt.bmWidth*imbt.bmHeight==0) + { + DeleteObject(ici.hbmColor); + DeleteObject(ici.hbmMask); + return 0; + } + GetObject(ici.hbmMask,sizeof(BITMAP),&immaskbt); + cy=imbt.bmHeight; + + if (imbt.bmBitsPixel!=32) + { + HDC tempDC1; + HBITMAP otBmp; + no32bit=TRUE; + tempDC1=CreateCompatibleDC(hdcDst); + tBmp=ske_CreateDIB32(imbt.bmWidth,imbt.bmHeight); + if (tBmp) + { + GetObject(tBmp,sizeof(BITMAP),&imbt); + otBmp=(HBITMAP)SelectObject(tempDC1,tBmp); + DrawIconEx(tempDC1,0,0,hIcon,imbt.bmWidth,imbt.bmHeight,istepIfAniCur,hbrFlickerFreeDraw,DI_IMAGE); + noMirrorMask=TRUE; + + } + SelectObject(tempDC1,otBmp); + mod_DeleteDC(tempDC1); + } + /* + if (imbt.bmBitsPixel!=32) + { + HDC tempDC1; + HBITMAP otBmp; + no32bit=TRUE; + tempDC1=ske_RequestBufferDC(hdcDst,BUFFER_DRAWICON,imbt.bmWidth,imbt.bmHeight); + if (tempDC1) + { + DrawIconEx(tempDC1,0,0,hIcon,imbt.bmWidth,imbt.bmHeight,istepIfAniCur,hbrFlickerFreeDraw,DI_IMAGE); + noMirrorMask=TRUE; + ske_ReleaseBufferDC(tempDC1,2000); //keep buffer for 2 seconds + } + } + */ + if (imbt.bmBits==NULL) + { + NoDIBImage=TRUE; + imimagbits=(BYTE*)malloc(cy*imbt.bmWidthBytes); + GetBitmapBits(ici.hbmColor,cy*imbt.bmWidthBytes,(void*)imimagbits); + } + else imimagbits=(BYTE*)imbt.bmBits; + + + if (immaskbt.bmBits==NULL) + { + immaskbits=(BYTE*)malloc(cy*immaskbt.bmWidthBytes); + GetBitmapBits(ici.hbmMask,cy*immaskbt.bmWidthBytes,(void*)immaskbits); + } + else + immaskbits=(BYTE*)immaskbt.bmBits; + icy=imbt.bmHeight; + cx=imbt.bmWidth; + imDC=CreateCompatibleDC(hdcDst); + imBmp=ske_CreateDIB32Point(cx,icy,(void**)&imbits); + oldBmp=(HBITMAP)SelectObject(imDC,imBmp); + if (imbits!=NULL && imimagbits!=NULL && immaskbits!=NULL) + { + int x; int y; + int bottom,right,top,h; + int mwb,mwb2; + mwb=immaskbt.bmWidthBytes; + mwb2=imbt.bmWidthBytes; + bottom=icy; + right=cx; + top=0; + h=icy; + for (y=top;(y>3))))!=0; + if (mask)// && !hasalpha) + { + if (!hasalpha) + { *dest=0; continue; } + else + { + if (((BYTE*)src)[3]>0 ) + a = ((BYTE*)src)[3]; + else + a = 0; + } + } + else if (hasalpha || hasmask) + a=(((BYTE*)src)[3]>0?((BYTE*)src)[3]:255); + else if (!hasalpha && !hasmask) + a=255; + else { *dest=0; continue; } + } + if (a>0) + { + ((BYTE*)dest)[3]=a; + ((BYTE*)dest)[0]=((BYTE*)src)[0]*a/255; + ((BYTE*)dest)[1]=((BYTE*)src)[1]*a/255; + ((BYTE*)dest)[2]=((BYTE*)src)[2]*a/255; + } + else + *dest=0; + } + } + } + { + BLENDFUNCTION bf={AC_SRC_OVER, diFlags&128, alpha, AC_SRC_ALPHA }; + ske_AlphaBlend(hdcDst,xLeft,yTop,cxWidth, cyWidth, imDC,0,0, cx,icy,bf); + } + if (immaskbt.bmBits==NULL) free(immaskbits); + if (imbt.bmBits==NULL) free(imimagbits); + SelectObject(imDC,oldBmp); + DeleteObject(imBmp); + if(no32bit)DeleteObject(tBmp); + DeleteObject(ici.hbmColor); + DeleteObject(ici.hbmMask); + SelectObject(imDC,GetStockObject(DEFAULT_GUI_FONT)); + mod_DeleteDC(imDC); + return 1;// DrawIconExS(hdc,xLeft,yTop,hIcon,cxWidth,cyWidth,istepIfAniCur,hbrFlickerFreeDraw,diFlags); +} + + + +int ske_PrepeareImageButDontUpdateIt(RECT * r) +{ + if (g_CluiData.fLayered) + { + mutex_bLockUpdate=1; + ske_DrawNonFramedObjects(TRUE,r); + ske_ValidateFrameImageProc(r); + mutex_bLockUpdate=0; + return 0; + } + else + { + return ske_ReCreateBackImage(FALSE,r); + } + return 0; +} + +int ske_RedrawCompleteWindow() +{ + if (g_CluiData.fLayered) + { + ske_DrawNonFramedObjects(TRUE,0); + CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,0,0); + } + else + { + RedrawWindow(pcli->hwndContactList,NULL,NULL,RDW_ALLCHILDREN|RDW_ERASE|RDW_INVALIDATE|RDW_FRAME); + } + return 0; +} +// Request to repaint frame or change/drop callback data +// wParam = hWnd of called frame +// lParam = pointer to sPaintRequest (or NULL to redraw all) +// return 2 - already queued, data updated, 1-have been queued, 0 - failure + +static INT_PTR ske_Service_UpdateFrameImage(WPARAM wParam, LPARAM lParam) // Immideately recall paint routines for frame and refresh image +{ + if ( MirandaLoading() ) return 0; + + RECT wnd; + FRAMEWND *frm; + BOOL NoCancelPost=0; + BOOL IsAnyQueued=0; + if (!g_CluiData.mutexOnEdgeSizing) + GetWindowRect(pcli->hwndContactList,&wnd); + else + wnd=g_rcEdgeSizingRect; + if (!g_CluiData.fLayered) + { + RedrawWindow((HWND)wParam,NULL,NULL,RDW_UPDATENOW|RDW_ERASE|RDW_INVALIDATE|RDW_FRAME); + return 0; + } + if (g_pCachedWindow==NULL) ske_ValidateFrameImageProc(&wnd); + else if (g_pCachedWindow->Width!=wnd.right-wnd.left || g_pCachedWindow->Height!=wnd.bottom-wnd.top) ske_ValidateFrameImageProc(&wnd); + else if (wParam==0) ske_ValidateFrameImageProc(&wnd); + else // all Ok Update Single Frame + { + // TO BE LOCKED OR PROXIED + frm=FindFrameByItsHWND((HWND)wParam); + if (!frm) ske_ValidateFrameImageProc(&wnd); + // Validate frame, update window image and remove it from queue + else + { + if(frm->UpdateRgn) + { + DeleteObject(frm->UpdateRgn); + frm->UpdateRgn=0; + } + ske_ValidateSingleFrameImage(frm,0); + ske_UpdateWindowImage(); + NoCancelPost=1; + //-- Remove frame from queue + if (flag_bUpdateQueued) + { + int i; + frm->bQueued=0; + for(i=0;ifloating)) return InvalidateRect((HWND)wParam,pr?(RECT*)&(pr->rcUpdate):NULL,FALSE); + if (frm) + { + if (frm->PaintCallbackProc!=NULL) + { + frm->PaintData=(sPaintRequest *)pr; + frm->bQueued=1; + if (pr) + { + HRGN r2; + if (!IsRectEmpty(&pr->rcUpdate)) + { + RECT rcClient; + RECT rcUpdate; + GetClientRect(frm->hWnd,&rcClient); + IntersectRect( &rcUpdate, &rcClient, &pr->rcUpdate ); + if ( IsRectEmpty( &rcUpdate ) ) + return 0; + r2=CreateRectRgn( rcUpdate.left, rcUpdate.top, rcUpdate.right, rcUpdate.bottom ); + } + else + { + RECT r; + GetClientRect(frm->hWnd,&r); + r2=CreateRectRgn(r.left,r.top,r.right,r.bottom); + } + if(!frm->UpdateRgn) + { + frm->UpdateRgn=CreateRectRgn(0,0,1,1); + CombineRgn(frm->UpdateRgn,r2,0,RGN_COPY); + } + else CombineRgn(frm->UpdateRgn,frm->UpdateRgn,r2,RGN_OR); + DeleteObject(r2); + } + + } + } + else + { + Sync( QueueAllFramesUpdating, (BYTE)1 ); + } + } + else + Sync( QueueAllFramesUpdating , (BYTE)1 ); + if (!flag_bUpdateQueued||g_flag_bPostWasCanceled) + if (PostMessage(pcli->hwndContactList,UM_UPDATE,0,0)) + { + flag_bUpdateQueued=1; + g_flag_bPostWasCanceled=0; + } + return 1; +} + + +static int ske_ValidateSingleFrameImage(FRAMEWND * Frame, BOOL SkipBkgBlitting) // Calling frame paint proc +{ + if (!g_pCachedWindow) { TRACE("ske_ValidateSingleFrameImage calling without cached\n"); return 0;} + if (Frame->hWnd==(HWND)-1 && !Frame->PaintCallbackProc) { TRACE("ske_ValidateSingleFrameImage calling without FrameProc\n"); return 0;} + { // if ok update image + HDC hdc; + HBITMAP o,n; + RECT rcPaint,wnd; + RECT ru={0}; + int w,h,x,y; + int w1,h1,x1,y1; + + CLUI_SizingGetWindowRect(pcli->hwndContactList,&wnd); + rcPaint=Frame->wndSize; + { + int dx,dy,bx,by; + if (g_CluiData.mutexOnEdgeSizing) + { + dx=rcPaint.left-wnd.left; + dy=rcPaint.top-wnd.top; + bx=rcPaint.right-wnd.right; + by=rcPaint.bottom-wnd.bottom; + wnd=g_rcEdgeSizingRect; + rcPaint.left=wnd.left+dx; + rcPaint.top=wnd.top+dy; + rcPaint.right=wnd.right+bx; + rcPaint.bottom=wnd.bottom+by; + } + } + //OffsetRect(&rcPaint,-wnd.left,-wnd.top); + w=rcPaint.right-rcPaint.left; + h=rcPaint.bottom-rcPaint.top; + if (w<=0 || h<=0) + { + TRACE("Frame size smaller than 0\n"); + return 0; + } + x=rcPaint.left; + y=rcPaint.top; + hdc=CreateCompatibleDC(g_pCachedWindow->hImageDC); + n=ske_CreateDIB32(w,h); + o=(HBITMAP)SelectObject(hdc,n); + { + if (Frame->UpdateRgn && !SkipBkgBlitting) + { + GetRgnBox(Frame->UpdateRgn,&ru); + { + RECT rc; + GetClientRect(Frame->hWnd,&rc); + if (ru.top<0) ru.top=0; + if (ru.left<0) ru.left=0; + if (ru.right>rc.right) ru.right=rc.right; + if (ru.bottom>rc.bottom) ru.bottom=rc.bottom; + } + if (!IsRectEmpty(&ru)) + { + x1=ru.left; + y1=ru.top; + w1=ru.right-ru.left; + h1=ru.bottom-ru.top; + } + else + {x1=0; y1=0; w1=w; h1=h;} + // copy image at hdc + if (SkipBkgBlitting) //image already at foreground + { + BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hImageDC,x+x1,y+y1,SRCCOPY); + } + else + { + BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hBackDC,x+x1,y+y1,SRCCOPY); + } + Frame->PaintCallbackProc(Frame->hWnd,hdc,&ru,Frame->UpdateRgn, Frame->dwFlags,Frame->PaintData); + } + else + { + HRGN rgnUpdate; + RECT r; + GetClientRect(Frame->hWnd,&r); + rgnUpdate=CreateRectRgn(r.left,r.top,r.right,r.bottom); + ru=r; + if (!IsRectEmpty(&ru)) + { + x1=ru.left; + y1=ru.top; + w1=ru.right-ru.left; + h1=ru.bottom-ru.top; + } + else + {x1=0; y1=0; w1=w; h1=h;} + // copy image at hdc + if (SkipBkgBlitting) //image already at foreground + { + BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hImageDC,x+x1,y+y1,SRCCOPY); + } + else + { + BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hBackDC,x+x1,y+y1,SRCCOPY); + } + Frame->PaintCallbackProc(Frame->hWnd,hdc,&r,rgnUpdate, Frame->dwFlags,Frame->PaintData); + ru=r; + DeleteObject(rgnUpdate); + } + DeleteObject(Frame->UpdateRgn); + Frame->UpdateRgn=0; + } + if (!IsRectEmpty(&ru)) + { + x1=ru.left; + y1=ru.top; + w1=ru.right-ru.left; + h1=ru.bottom-ru.top; + } + else + {x1=0; y1=0; w1=w; h1=h;} + /* if (!SkipBkgBlitting) + { + BitBlt(g_pCachedWindow->hImageDC,x+x1,y+y1,w1,h1,g_pCachedWindow->hBackDC,x+x1,y+y1,SRCCOPY); + } + + */ + { + //BLENDFUNCTION bf={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; + BitBlt(g_pCachedWindow->hImageDC,x+x1,y+y1,w1,h1,hdc,x1,y1,SRCCOPY); + //BLENDFUNCTION bf={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; + //MyAlphaBlend(g_pCachedWindow->hImageDC,x+x1,y+y1,w1,h1,hdc,x1,y1,w1,h1,bf); + } + + if ( fnGetScrollBarInfo && (GetWindowLong(Frame->hWnd,GWL_STYLE) & WS_VSCROLL)) + { + //Draw vertical scroll bar + // + RECT rThumb; + RECT rUpBtn; + RECT rDnBtn; + RECT rLine; + int dx,dy; + SCROLLBARINFO si={0}; + si.cbSize=sizeof(SCROLLBARINFO); + fnGetScrollBarInfo(Frame->hWnd,OBJID_VSCROLL,&si); + rLine=(si.rcScrollBar); + rUpBtn=rLine; + rDnBtn=rLine; + rThumb=rLine; + + rUpBtn.bottom=rUpBtn.top+si.dxyLineButton; + rDnBtn.top=rDnBtn.bottom-si.dxyLineButton; + rThumb.top=rLine.top+si.xyThumbTop; + rThumb.bottom=rLine.top+si.xyThumbBottom; + { + dx=Frame->wndSize.right-rLine.right; + dy=-rLine.top+Frame->wndSize.top; + } + OffsetRect(&rLine,dx,dy); + OffsetRect(&rUpBtn,dx,dy); + OffsetRect(&rDnBtn,dx,dy); + OffsetRect(&rThumb,dx,dy); + BitBlt(g_pCachedWindow->hImageDC,rLine.left,rLine.top,rLine.right-rLine.left,rLine.bottom-rLine.top,g_pCachedWindow->hBackDC,rLine.left,rLine.top,SRCCOPY); + { + char req[255]; + _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=Back",Frame->szName); + SkinDrawGlyph(g_pCachedWindow->hImageDC,&rLine,&rLine,req); + _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=Thumb",Frame->szName); + SkinDrawGlyph(g_pCachedWindow->hImageDC,&rThumb,&rThumb,req); + _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=UpLineButton",Frame->szName); + SkinDrawGlyph(g_pCachedWindow->hImageDC,&rUpBtn,&rUpBtn,req); + _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=DownLineButton",Frame->szName); + SkinDrawGlyph(g_pCachedWindow->hImageDC,&rDnBtn,&rDnBtn,req); + } + } + + SelectObject(hdc,o); + DeleteObject(n); + mod_DeleteDC(hdc); + } + return 1; +} + +int ske_BltBackImage (HWND destHWND, HDC destDC, RECT * BltClientRect) +{ + POINT ptMainWnd={0}; + POINT ptChildWnd={0}; + RECT from={0}; + RECT w={0}; + if (g_CluiData.fDisableSkinEngine) + { + FillRect(destDC,BltClientRect,GetSysColorBrush(COLOR_3DFACE)); + return 0; + } + ske_ReCreateBackImage(FALSE,NULL); + if (BltClientRect) w=*BltClientRect; + else GetClientRect(destHWND,&w); + ptChildWnd.x=w.left; + ptChildWnd.y=w.top; + ClientToScreen(destHWND,&ptChildWnd); + ClientToScreen(pcli->hwndContactList,&ptMainWnd); + //TODO if main not relative to client area + return BitBlt(destDC,w.left,w.top,(w.right-w.left),(w.bottom-w.top),g_pCachedWindow->hBackDC,(ptChildWnd.x-ptMainWnd.x),(ptChildWnd.y-ptMainWnd.y),SRCCOPY); + +} +int ske_ReCreateBackImage(BOOL Erase,RECT *w) +{ + HBITMAP hb2; + RECT wnd={0}; + BOOL IsNewCache=0; + if (g_CluiData.fDisableSkinEngine) return 0; + GetClientRect(pcli->hwndContactList,&wnd); + if (w) wnd=*w; + //-- Check cached. + if (g_pCachedWindow==NULL) + { + //-- Create New Cache + { + g_pCachedWindow=(CURRWNDIMAGEDATA*)mir_calloc(sizeof(CURRWNDIMAGEDATA)); + g_pCachedWindow->hScreenDC=GetDC(NULL); + g_pCachedWindow->hBackDC=CreateCompatibleDC(g_pCachedWindow->hScreenDC); + g_pCachedWindow->hImageDC=CreateCompatibleDC(g_pCachedWindow->hScreenDC); + g_pCachedWindow->Width=wnd.right-wnd.left; + g_pCachedWindow->Height=wnd.bottom-wnd.top; + if (g_pCachedWindow->Width!=0 && g_pCachedWindow->Height!=0) + { + g_pCachedWindow->hImageDIB=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte)); + g_pCachedWindow->hBackDIB=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte)); + g_pCachedWindow->hImageOld=(HBITMAP)SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageDIB); + g_pCachedWindow->hBackOld=(HBITMAP)SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackDIB); + } + } + IsNewCache=1; + } + if (g_pCachedWindow->Width!=wnd.right-wnd.left || g_pCachedWindow->Height!=wnd.bottom-wnd.top) + { + HBITMAP hb1=NULL,hb2=NULL; + g_pCachedWindow->Width=wnd.right-wnd.left; + g_pCachedWindow->Height=wnd.bottom-wnd.top; + if (g_pCachedWindow->Width!=0 && g_pCachedWindow->Height!=0) + { + hb1=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte)); + hb2=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte)); + SelectObject(g_pCachedWindow->hImageDC,hb1); + SelectObject(g_pCachedWindow->hBackDC,hb2); + } + else + { + SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageOld); + SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackOld); + } + if (g_pCachedWindow->hImageDIB) DeleteObject(g_pCachedWindow->hImageDIB); + if (g_pCachedWindow->hBackDIB) DeleteObject(g_pCachedWindow->hBackDIB); + g_pCachedWindow->hImageDIB=hb1; + g_pCachedWindow->hBackDIB=hb2; + IsNewCache=1; + } + if ((Erase || IsNewCache )&& (g_pCachedWindow->Width!=0 && g_pCachedWindow->Height!=0)) + { + + hb2=ske_CreateDIB32(g_pCachedWindow->Width,g_pCachedWindow->Height); + SelectObject(g_pCachedWindow->hBackDC,hb2); + DeleteObject(g_pCachedWindow->hBackDIB); + g_pCachedWindow->hBackDIB=hb2; + FillRect(g_pCachedWindow->hBackDC,&wnd,GetSysColorBrush(COLOR_BTNFACE)); + SkinDrawGlyph(g_pCachedWindow->hBackDC,&wnd,&wnd,"Main,ID=Background,Opt=Non-Layered"); + ske_SetRectOpaque(g_pCachedWindow->hBackDC,&wnd); + } + return 1; +} +int ske_DrawNonFramedObjects(BOOL Erase,RECT *r) +{ + RECT w,wnd; + if (r) w=*r; + else CLUI_SizingGetWindowRect(pcli->hwndContactList,&w); + if (!g_CluiData.fLayered) return ske_ReCreateBackImage(FALSE,0); + if (g_pCachedWindow==NULL) + return ske_ValidateFrameImageProc(&w); + + wnd=w; + OffsetRect(&w, -w.left, -w.top); + if (Erase) + { + HBITMAP hb2; + hb2=ske_CreateDIB32(g_pCachedWindow->Width,g_pCachedWindow->Height); + SelectObject(g_pCachedWindow->hBackDC,hb2); + DeleteObject(g_pCachedWindow->hBackDIB); + g_pCachedWindow->hBackDIB=hb2; + } + + SkinDrawGlyph(g_pCachedWindow->hBackDC,&w,&w,"Main,ID=Background"); + //--Draw frames captions + { + int i; + for(i=0;ihBackDC, &rc, g_pfwFrames[i].id ); + } + } + g_mutex_bLockUpdating=1; + + flag_bJustDrawNonFramedObjects=1; + return 0; +} +int ske_ValidateFrameImageProc(RECT * r) // Calling queued frame paint procs and refresh image +{ + RECT wnd={0}; + BOOL IsNewCache=0; + BOOL IsForceAllPainting=0; + if (r) wnd=*r; + else GetWindowRect(pcli->hwndContactList,&wnd); + if (wnd.right-wnd.left==0 || wnd.bottom-wnd.top==0) return 0; + g_mutex_bLockUpdating=1; + //-- Check cached. + if (g_pCachedWindow==NULL) + { + //-- Create New Cache + { + g_pCachedWindow=(CURRWNDIMAGEDATA*)mir_calloc(sizeof(CURRWNDIMAGEDATA)); + g_pCachedWindow->hScreenDC=GetDC(NULL); + g_pCachedWindow->hBackDC=CreateCompatibleDC(g_pCachedWindow->hScreenDC); + g_pCachedWindow->hImageDC=CreateCompatibleDC(g_pCachedWindow->hScreenDC); + g_pCachedWindow->Width=wnd.right-wnd.left; + g_pCachedWindow->Height=wnd.bottom-wnd.top; + g_pCachedWindow->hImageDIB=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte)); + g_pCachedWindow->hBackDIB=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte)); + g_pCachedWindow->hImageOld=(HBITMAP)SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageDIB); + g_pCachedWindow->hBackOld=(HBITMAP)SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackDIB); + } + IsNewCache=1; + } + if (g_pCachedWindow->Width!=wnd.right-wnd.left || g_pCachedWindow->Height!=wnd.bottom-wnd.top) + { + HBITMAP hb1,hb2; + g_pCachedWindow->Width=wnd.right-wnd.left; + g_pCachedWindow->Height=wnd.bottom-wnd.top; + hb1=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte)); + hb2=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte)); + SelectObject(g_pCachedWindow->hImageDC,hb1); + SelectObject(g_pCachedWindow->hBackDC,hb2); + DeleteObject(g_pCachedWindow->hImageDIB); + DeleteObject(g_pCachedWindow->hBackDIB); + g_pCachedWindow->hImageDIB=hb1; + g_pCachedWindow->hBackDIB=hb2; + IsNewCache=1; + } + if (IsNewCache) + { + ske_DrawNonFramedObjects(0,&wnd); + IsForceAllPainting=1; + } + if (flag_bJustDrawNonFramedObjects) + { + IsForceAllPainting=1; + flag_bJustDrawNonFramedObjects=0; + } + if (IsForceAllPainting) + { + BitBlt(g_pCachedWindow->hImageDC,0,0,g_pCachedWindow->Width,g_pCachedWindow->Height,g_pCachedWindow->hBackDC,0,0,SRCCOPY); + Sync( QueueAllFramesUpdating, (BYTE)1 ); + } + //-- Validating frames + { + int i; + for(i=0;ihwndContactList,&r); + return ske_UpdateWindowImageRect(&r); + } + else + ske_ReCreateBackImage(FALSE,0); + ske_ApplyTransluency(); + return 0; +} + + +int ske_UpdateWindowImageRect(RECT * r) // Update window with current image and +{ + //if not validity -> ValidateImageProc + //else Update using current alpha + RECT wnd=*r; + + if (!g_CluiData.fLayered) return ske_ReCreateBackImage(FALSE,0); + if (g_pCachedWindow==NULL) return ske_ValidateFrameImageProc(&wnd); + if (g_pCachedWindow->Width!=wnd.right-wnd.left || g_pCachedWindow->Height!=wnd.bottom-wnd.top) return ske_ValidateFrameImageProc(&wnd); + if (g_flag_bFullRepaint) + { + g_flag_bFullRepaint=0; + return ske_ValidateFrameImageProc(&wnd); + } + ske_JustUpdateWindowImageRect(&wnd); + return 0; +} + +void ske_ApplyTransluency() +{ + int IsTransparancy; + HWND hwnd=pcli->hwndContactList; + BOOL layered=(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED)?TRUE:FALSE; + + IsTransparancy=g_CluiData.fSmoothAnimation || g_bTransparentFlag; + if (!g_bTransparentFlag && !g_CluiData.fSmoothAnimation && g_CluiData.bCurrentAlpha!=0) + g_CluiData.bCurrentAlpha=255; + if (!g_CluiData.fLayered && (/*(g_CluiData.bCurrentAlpha==255)||*/(g_proc_SetLayeredWindowAttributesNew && IsTransparancy))) + { + if (!layered) SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED); + if (g_proc_SetLayeredWindowAttributesNew) g_proc_SetLayeredWindowAttributesNew(hwnd, RGB(0,0,0), (BYTE)g_CluiData.bCurrentAlpha, LWA_ALPHA); + } + + AniAva_RedrawAllAvatars(FALSE); + return; +} + +int ske_JustUpdateWindowImage() +{ + RECT r; + if (!g_CluiData.fLayered) + { + ske_ApplyTransluency(); + return 0; + } + GetWindowRect(pcli->hwndContactList,&r); + return ske_JustUpdateWindowImageRect(&r); +} +int ske_JustUpdateWindowImageRect(RECT * rty) +//Update window image +{ + BLENDFUNCTION bf={AC_SRC_OVER, 0,g_CluiData.bCurrentAlpha, AC_SRC_ALPHA }; + POINT dest={0}, src={0}; + int res; + RECT wnd=*rty; + + RECT rect; + SIZE sz={0}; + + if (!g_CluiData.fLayered) + { + ske_ApplyTransluency(); + return 0; + } + if (!pcli->hwndContactList) return 0; + rect=wnd; + dest.x=rect.left; + dest.y=rect.top; + sz.cx=rect.right-rect.left; + sz.cy=rect.bottom-rect.top; + if (g_proc_UpdateLayeredWindow && g_CluiData.fLayered) + { + if (!(GetWindowLong(pcli->hwndContactList, GWL_EXSTYLE)&WS_EX_LAYERED)) + SetWindowLong(pcli->hwndContactList,GWL_EXSTYLE, GetWindowLong(pcli->hwndContactList, GWL_EXSTYLE) |WS_EX_LAYERED); + Sync( SetAlpha, g_CluiData.bCurrentAlpha ); + + res=g_proc_UpdateLayeredWindow(pcli->hwndContactList,g_pCachedWindow->hScreenDC,&dest,&sz,g_pCachedWindow->hImageDC,&src,RGB(1,1,1),&bf,ULW_ALPHA); + g_CluiData.fAeroGlass = false; + CLUI_UpdateAeroGlass(); + } + else InvalidateRect(pcli->hwndContactList,NULL,TRUE); + return 0; +} + +int ske_DrawImageAt(HDC hdc, RECT *rc) +{ + BLENDFUNCTION bf={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; + BitBlt(g_pCachedWindow->hImageDC,rc->left,rc->top,rc->right-rc->left,rc->bottom-rc->top,g_pCachedWindow->hBackDC,rc->left,rc->top,SRCCOPY); + ske_AlphaBlend(g_pCachedWindow->hImageDC,rc->left,rc->top,rc->right-rc->left,rc->bottom-rc->top,hdc,0,0,rc->right-rc->left,rc->bottom-rc->top,bf); + if (!g_mutex_bLockUpdating) + ske_UpdateWindowImage(); + return 0; +} + +HBITMAP ske_GetCurrentWindowImage() +{ + return g_pCachedWindow->hImageDIB; +} + +/* +* Glyph text routine +*/ + +static DWORD ske_HexToARGB(char * Hex) +{ + char buf[10]={0}; + char buf2[11]={0}; + char * st; + BYTE alpha; + DWORD AARRGGBB=0; + _snprintf(buf,10,"%s\n",Hex); + if (buf[1]=='x' || buf[1]=='X') + _snprintf(buf2,11,"0x%s\n",buf+2); + else + _snprintf(buf2,11,"0x%s\n",buf); + buf2[10]='\0'; + AARRGGBB=strtoul(buf2,&st,16); + alpha=(BYTE)((AARRGGBB&0xFF000000)>>24); + alpha=255-((alpha==0)?255:alpha); + AARRGGBB=(alpha<<24)+((AARRGGBB&0x00FF0000)>>16)+((AARRGGBB&0x000000FF)<<16)+(AARRGGBB&0x0000FF00); + return AARRGGBB; +} + +static TCHAR *ske_ReAppend(TCHAR *lfirst, TCHAR * lsecond, int len) +{ + int l1=lfirst?lstrlen(lfirst):0; + int l2=(len?len:(lstrlen(lsecond)+1)); + TCHAR *buf=(TCHAR *)mir_alloc((l1+l2+1)*sizeof(TCHAR)); + if (lfirst) memmove(buf,lfirst,l1*sizeof(TCHAR)); + memmove(buf+l1,lsecond,l2*sizeof(TCHAR)); + if (lfirst) mir_free(lfirst); + if (len) buf[l1+l2]=_T('\0'); + return buf; +} + +TCHAR* ske_ReplaceVar(TCHAR *var) +{ + if (!var) return mir_tstrdup(_T("")); + if (!lstrcmpi(var,TEXT("Profile"))) + { + char buf[MAX_PATH]={0}; + CallService(MS_DB_GETPROFILENAME,(WPARAM)MAX_PATH,(LPARAM)buf); + { + int i=strlen(buf); + while (buf[i]!='.' && i>0) i--; + buf[i]='\0'; + } + mir_free_and_nill(var); +#ifdef UNICODE + return mir_a2u(buf); +#else + return mir_strdup(buf); +#endif + } + + mir_free_and_nill(var); + return mir_tstrdup(_T("")); +} +TCHAR *ske_ParseText(TCHAR *stzText) +{ + int len=lstrlen(stzText); + TCHAR *result=NULL; + int stpos=0; + int curpos=0; + + while(curpos0) + result=ske_ReAppend(result,stzText+stpos,curpos-stpos); + stpos=curpos+1; + curpos++; + //3 find second % + while(curpos0) + { + TCHAR *var=(TCHAR *)mir_alloc((curpos-stpos+1)*sizeof(TCHAR)); + memmove(var,stzText+stpos,(curpos-stpos)*sizeof(TCHAR)); + var[curpos-stpos]=(TCHAR)'\0'; + var=ske_ReplaceVar(var); + result=ske_ReAppend(result,var,0); + mir_free_and_nill(var); + } + else + result=ske_ReAppend(result,_T("%"),0); + curpos++; + stpos=curpos; + } + else + { + // if (curpos-stpos>0) + // result=ske_ReAppend(result,stzText+stpos,curpos-stpos); + break; + } + } + else + { + if (curpos-stpos>0) + result=ske_ReAppend(result,stzText+stpos,curpos-stpos); + break; + } + } + return result; +} +/* +* Parse text object string, find glyph object and add text to it. +* szGlyphTextID and Define string is: +* t[szGlyphTextID]=s[HostObjectID],[Left],[Top],[Right],[Bottom],[LTRBHV],[FontID],[Color1],[reservedforColor2],[Text] +*/ +static void OLDske_AddParseTextGlyphObject(char * szGlyphTextID,char * szDefineString,SKINOBJECTSLIST *Skin) +{ + + GLYPHOBJECT *globj=NULL; + { + char buf[255]={0}; + GetParamN(szDefineString,buf,sizeof(buf),0,',',TRUE); + if (strlen(buf)) + { + SKINOBJECTDESCRIPTOR * lpobj; + lpobj=ske_FindObjectByName(buf,OT_GLYPHOBJECT,Skin); + if (lpobj) + globj=(GLYPHOBJECT*)lpobj->Data; + } + if (globj) + { + GLYPHTEXT * glText; + + if (!globj->plTextList) + { + globj->plTextList=li.List_Create(0,1); + globj->plTextList->sortFunc=ske_SortTextGlyphObjectFunc; + } + glText=(GLYPHTEXT*)mir_calloc(sizeof(GLYPHTEXT)); + glText->szGlyphTextID=mir_strdup(szGlyphTextID); + glText->szObjectName=mir_strdup(buf); + glText->iLeft=atoi(GetParamN(szDefineString,buf,sizeof(buf),1,',',TRUE)); + glText->iTop=atoi(GetParamN(szDefineString,buf,sizeof(buf),2,',',TRUE)); + glText->iRight=atoi(GetParamN(szDefineString,buf,sizeof(buf),3,',',TRUE)); + glText->iBottom=atoi(GetParamN(szDefineString,buf,sizeof(buf),4,',',TRUE)); + { + memset(buf,0,6); + GetParamN(szDefineString,buf,sizeof(buf),5,',',TRUE); + buf[0]&=95; buf[1]&=95; buf[2]&=95; buf[3]&=95; buf[4]&=95; buf[5]&=95; //to uppercase: &01011111 (0-95) + glText->RelativeFlags= + (buf[0]=='C'?1:((buf[0]=='R')?2:0)) //[BC][RC][BC][RC] --- Left relative + |(buf[1]=='C'?4:((buf[1]=='B')?8:0)) // | | |--------- Top relative + |(buf[2]=='C'?16:((buf[2]=='R')?32:0)) // | |--------------Right relative + |(buf[3]=='C'?64:((buf[3]=='B')?128:0)); // |------------------Bottom relative + glText->dwFlags=(buf[4]=='C'?DT_CENTER:((buf[4]=='R')?DT_RIGHT:DT_LEFT)) + |(buf[5]=='C'?DT_VCENTER:((buf[5]=='B')?DT_BOTTOM:DT_TOP)); + } + glText->szFontID=mir_strdup(GetParamN(szDefineString,buf,sizeof(buf),6,',',TRUE)); + + glText->dwColor=ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),7,',',TRUE)); + glText->dwShadow=ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),8,',',TRUE)); +#ifdef _UNICODE + glText->stValueText=mir_a2u(GetParamN(szDefineString,buf,sizeof(buf),9,',',TRUE)); + glText->stText=ske_ParseText(glText->stValueText); +#else + glText->stValueText=mir_strdup(GetParamN(szDefineString,buf,sizeof(buf),9,',',TRUE)); + glText->stText=ske_ParseText(glText->stValueText); +#endif + li.List_Insert(globj->plTextList,(void*)glText,globj->plTextList->realCount); + qsort(globj->plTextList->items,globj->plTextList->realCount,sizeof(void*),(int(*)(const void*, const void*))globj->plTextList->sortFunc); + } + } +} + + +static void ske_AddParseTextGlyphObject(char * szGlyphTextID,char * szDefineString,SKINOBJECTSLIST *Skin) +{ + char buf[255]={0}; + GetParamN(szDefineString,buf,sizeof(buf),0,',',TRUE); + if (strlen(buf)) + { + GLYPHTEXT * glText; + glText=(GLYPHTEXT*)mir_calloc(sizeof(GLYPHTEXT)); + glText->szGlyphTextID=mir_strdup(szGlyphTextID); + glText->szObjectName=mir_strdup(buf); + glText->iLeft=atoi(GetParamN(szDefineString,buf,sizeof(buf),1,',',TRUE)); + glText->iTop=atoi(GetParamN(szDefineString,buf,sizeof(buf),2,',',TRUE)); + glText->iRight=atoi(GetParamN(szDefineString,buf,sizeof(buf),3,',',TRUE)); + glText->iBottom=atoi(GetParamN(szDefineString,buf,sizeof(buf),4,',',TRUE)); + { + memset(buf,0,6); + GetParamN(szDefineString,buf,sizeof(buf),5,',',TRUE); + buf[0]&=95; buf[1]&=95; buf[2]&=95; buf[3]&=95; buf[4]&=95; buf[5]&=95; //to uppercase: &01011111 (0-95) + glText->RelativeFlags= + (buf[0]=='C'?1:((buf[0]=='R')?2:0)) //[BC][RC][BC][RC] --- Left relative + |(buf[1]=='C'?4:((buf[1]=='B')?8:0)) // | | |--------- Top relative + |(buf[2]=='C'?16:((buf[2]=='R')?32:0)) // | |--------------Right relative + |(buf[3]=='C'?64:((buf[3]=='B')?128:0)); // |------------------Bottom relative + glText->dwFlags=(buf[4]=='C'?DT_CENTER:((buf[4]=='R')?DT_RIGHT:DT_LEFT)) + |(buf[5]=='C'?DT_VCENTER:((buf[5]=='B')?DT_BOTTOM:DT_TOP)); + } + glText->szFontID=mir_strdup(GetParamN(szDefineString,buf,sizeof(buf),6,',',TRUE)); + + glText->dwColor=ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),7,',',TRUE)); + glText->dwShadow=ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),8,',',TRUE)); +#ifdef _UNICODE + glText->stValueText=mir_a2u(GetParamN(szDefineString,buf,sizeof(buf),9,',',TRUE)); + glText->stText=ske_ParseText(glText->stValueText); +#else + glText->stValueText=mir_strdup(GetParamN(szDefineString,buf,sizeof(buf),9,',',TRUE)); + glText->stText=ske_ParseText(glText->stValueText); +#endif + if (!Skin->pTextList) + Skin->pTextList=li.List_Create(0,1); + li.List_InsertPtr(Skin->pTextList,glText); + } +} + + +/* +* Parse font definition string. +* szGlyphTextID and Define string is: +* f[szFontID]=s[FontTypefaceName],[size],[BIU] +*/ +static void ske_AddParseSkinFont(char * szFontID,char * szDefineString,SKINOBJECTSLIST *Skin) +{ + //SortedList * gl_plSkinFonts=NULL; + SKINFONT * sf =NULL; + sf=(SKINFONT*)mir_calloc(sizeof(SKINFONT)); + if (sf) + { + { + char buf[255]; + int fntSize=0; + BOOL fntBold=FALSE, fntItalic=FALSE, fntUnderline=FALSE; + LOGFONTA logfont={0}; + logfont.lfCharSet=DEFAULT_CHARSET; + logfont.lfOutPrecision=OUT_DEFAULT_PRECIS; + logfont.lfClipPrecision=CLIP_DEFAULT_PRECIS; + logfont.lfQuality=DEFAULT_QUALITY; + logfont.lfPitchAndFamily=DEFAULT_PITCH|FF_DONTCARE; + + strncpy(logfont.lfFaceName,GetParamN(szDefineString,buf,sizeof(buf),0,',',TRUE),32); + logfont.lfHeight=atoi(GetParamN(szDefineString,buf,sizeof(buf),1,',',TRUE)); + if (logfont.lfHeight<0) + { + HDC hdc=CreateCompatibleDC(NULL); + logfont.lfHeight=(long)-MulDiv(logfont.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72); + mod_DeleteDC(hdc); + } + logfont.lfHeight=-logfont.lfHeight; + GetParamN(szDefineString,buf,sizeof(buf),2,',',TRUE); + buf[0]&=95; buf[1]&=95; buf[2]&=95; + logfont.lfWeight=(buf[0]=='B')?FW_BOLD:FW_NORMAL; + logfont.lfItalic=(buf[1]=='I')?1:0; + logfont.lfUnderline=(buf[2]=='U')?1:0; + + sf->hFont=CreateFontIndirectA(&logfont); + if (sf->hFont) + { + sf->szFontID=mir_strdup(szFontID); + if (!gl_plSkinFonts) + gl_plSkinFonts=li.List_Create(0,1); + if (gl_plSkinFonts) + { + li.List_Insert(gl_plSkinFonts,(void*)sf,gl_plSkinFonts->realCount); + } + } + + } + } + +} + +/* +HICON ske_CreateJoinedIcon_Old(HICON hBottom, HICON hTop,BYTE alpha) +{ +HDC tempDC; +HICON res=NULL; +HBITMAP oImage,nImage; +HBITMAP nMask; +ICONINFO iNew={0}; +ICONINFO iciBottom={0}; +ICONINFO iciTop={0}; +BITMAP bmp={0}; +SIZE sz={0}; +{ +if (!GetIconInfo(hBottom,&iciBottom)) return NULL; +GetObject(iciBottom.hbmColor,sizeof(BITMAP),&bmp); +sz.cx=bmp.bmWidth; sz.cy=bmp.bmHeight; +if(iciBottom.hbmColor) DeleteObject(iciBottom.hbmColor); +if(iciBottom.hbmMask) DeleteObject(iciBottom.hbmMask); +} +if (sz.cx==0 || sz.cy==0) return NULL; +tempDC=CreateCompatibleDC(NULL); +nImage=ske_CreateDIB32(sz.cx,sz.cy); +oImage=SelectObject(tempDC,nImage); +ske_DrawIconEx(tempDC,0,0,hBottom,sz.cx,sz.cy,0,NULL,DI_NORMAL); +ske_DrawIconEx(tempDC,0,0,hTop,sz.cx,sz.cy,0,NULL,DI_NORMAL|(alpha<<24)); +SelectObject(tempDC,oImage); +DeleteDC(tempDC); +{ +BYTE * p=malloc(sz.cx*sz.cy/8+10); +nMask=CreateBitmap(sz.cx,sz.cy,1,1,(void*)p); +iNew.fIcon=TRUE; +iNew.hbmColor=nImage; +iNew.hbmMask=nMask; +res=CreateIconIndirect(&iNew); +if (!res) +TRACE_ERROR(); +DeleteObject(nImage); +DeleteObject(nMask); +free(p); +} +return res; +} +*/ + + +/* +* ske_CheckHasAlfaChannel - checks if image has at least one BYTE in alpha chennel +* that is not a 0. (is image real 32 bit or just 24 bit) +*/ +static BOOL ske_CheckHasAlfaChannel(BYTE * from, int widthByte, int height) +{ + int i=0,j=0; + DWORD * pt=(DWORD*)from; + while (j>3)))&(0x01<<(7-(x&0x07))))!=0; +} +/* +* ske_Blend - alpha ske_Blend ARGB values of 2 pixels. X1 - underlaying, +* X2 - overlaying points. +*/ + +static DWORD ske_Blend(DWORD X1,DWORD X2, BYTE alpha) +{ + BYTE a1=(BYTE)(X1>>24); + BYTE a2=(BYTE)(((X2>>24)*alpha)>>8); + BYTE r1=(BYTE)(X1>>16); + BYTE r2=(BYTE)(X2>>16); + BYTE g1=(BYTE)(X1>>8); + BYTE g2=(BYTE)(X2>>8); + BYTE b1=(BYTE)(X1); + BYTE b2=(BYTE)(X2); + + BYTE a_1=~a1; + BYTE a_2=~a2; + WORD am=(WORD)a1*a_2; + + /* it is possible to use >>8 instead of /255 but it is require additional + * checking of alphavalues + */ + WORD ar=a1+(((WORD)a_1*a2)/255); + // if a2 more than 0 than result should be more + // or equal (if a1==0) to a2, else in combination + // with mask we can get here black points + + ar=(a2>ar)?a2:ar; + + if (ar==0) return 0; + + //else + { + WORD arm=ar*255; + WORD rr=(((WORD)r1*am+(WORD)r2*a2*255))/arm; + WORD gr=(((WORD)g1*am+(WORD)g2*a2*255))/arm; + WORD br=(((WORD)b1*am+(WORD)b2*a2*255))/arm; + return (ar<<24)|(rr<<16)|(gr<<8)|br; + } + +} +/* +* CreateJoinedIcon - creates new icon by drawing hTop over hBottom. +*/ +HICON ske_CreateJoinedIcon(HICON hBottom, HICON hTop, BYTE alpha) +{ + HDC tempDC; + HICON res=NULL; + HBITMAP oImage,nImage; + HBITMAP nMask; + BITMAP bmp={0}; + BYTE *ptPixels; + ICONINFO iNew={0}; + ICONINFO iciBottom={0}; + ICONINFO iciTop={0}; + + BITMAP bmp_top={0}; + BITMAP bmp_top_mask={0}; + + BITMAP bmp_bottom={0}; + BITMAP bmp_bottom_mask={0}; + + tempDC=CreateCompatibleDC(NULL); + nImage=ske_CreateDIB32Point(16,16,(void**)&ptPixels); + oImage=(HBITMAP)SelectObject(tempDC,nImage); + + GetIconInfo(hBottom,&iciBottom); + GetObject(iciBottom.hbmColor,sizeof(BITMAP),&bmp_bottom); + GetObject(iciBottom.hbmMask,sizeof(BITMAP),&bmp_bottom_mask); + + GetIconInfo(hTop,&iciTop); + GetObject(iciTop.hbmColor,sizeof(BITMAP),&bmp_top); + GetObject(iciTop.hbmMask,sizeof(BITMAP),&bmp_top_mask); + + if (bmp_bottom.bmBitsPixel==32 &&bmp_top.bmBitsPixel==32 && IsWinVerXPPlus()) + { + BYTE * BottomBuffer, * TopBuffer, * BottomMaskBuffer, * TopMaskBuffer; + BYTE * bb, * tb, * bmb, * tmb; + BYTE * db=ptPixels; + int vstep_d=16*4; + int vstep_b=bmp_bottom.bmWidthBytes; + int vstep_t=bmp_top.bmWidthBytes; + int vstep_bm=bmp_bottom_mask.bmWidthBytes; + int vstep_tm=bmp_top_mask.bmWidthBytes; + alpha=alpha?alpha:255; + if (bmp_bottom.bmBits) bb=BottomBuffer=(BYTE*)bmp_bottom.bmBits; + else + { + BottomBuffer=(BYTE*)malloc(bmp_bottom.bmHeight*bmp_bottom.bmWidthBytes); + GetBitmapBits(iciBottom.hbmColor,bmp_bottom.bmHeight*bmp_bottom.bmWidthBytes,BottomBuffer); + bb=BottomBuffer+vstep_b*(bmp_bottom.bmHeight-1); + vstep_b=-vstep_b; + } + if (bmp_top.bmBits) tb=TopBuffer=(BYTE*)bmp_top.bmBits; + else + { + TopBuffer=(BYTE*)malloc(bmp_top.bmHeight*bmp_top.bmWidthBytes); + GetBitmapBits(iciTop.hbmColor,bmp_top.bmHeight*bmp_top.bmWidthBytes,TopBuffer); + tb=TopBuffer+vstep_t*(bmp_top.bmHeight-1); + vstep_t=-vstep_t; + } + if (bmp_bottom_mask.bmBits) + { + BottomMaskBuffer=(BYTE*)bmp_bottom_mask.bmBits; + bmb=BottomMaskBuffer; + } + else + { + BottomMaskBuffer=(BYTE*)malloc(bmp_bottom_mask.bmHeight*bmp_bottom_mask.bmWidthBytes); + GetBitmapBits(iciBottom.hbmMask,bmp_bottom_mask.bmHeight*bmp_bottom_mask.bmWidthBytes,BottomMaskBuffer); + bmb=BottomMaskBuffer+vstep_bm*(bmp_bottom_mask.bmHeight-1); + vstep_bm=-vstep_bm; + + } + if (bmp_top_mask.bmBits) + { + TopMaskBuffer=(BYTE*)bmp_top_mask.bmBits; + tmb=TopMaskBuffer; + + } + else + { + TopMaskBuffer=(BYTE*)malloc(bmp_top_mask.bmHeight*bmp_top_mask.bmWidthBytes); + GetBitmapBits(iciTop.hbmMask,bmp_top_mask.bmHeight*bmp_top_mask.bmWidthBytes,TopMaskBuffer); + tmb=TopMaskBuffer+vstep_tm*(bmp_top_mask.bmHeight-1); + vstep_tm=-vstep_tm; + } + { + int x=0; int y=0; + BOOL topHasAlpha=ske_CheckHasAlfaChannel(TopBuffer,bmp_top.bmWidthBytes,bmp_top.bmHeight); + BOOL bottomHasAlpha=ske_CheckHasAlfaChannel(BottomBuffer,bmp_bottom.bmWidthBytes,bmp_bottom.bmHeight); + BOOL topHasMask=ske_CheckIconHasMask(TopMaskBuffer); + BOOL bottomHasMask=ske_CheckIconHasMask(BottomMaskBuffer); + for (y=0; y<16; y++) + { + for (x=0; x<16; x++) + { + BOOL mask_b=ske_GetMaskBit(bmb,x); + BOOL mask_t=ske_GetMaskBit(tmb,x); + DWORD bottom_d=((DWORD*)bb)[x]; + DWORD top_d=((DWORD*)tb)[x]; + if (topHasMask) + { + if (mask_t==1 && !topHasAlpha ) top_d&=0xFFFFFF; + else if (!topHasAlpha) top_d|=0xFF000000; + } + if (bottomHasMask) + { + if (mask_b==1 && !bottomHasAlpha) bottom_d&=0xFFFFFF; + else if (!bottomHasAlpha) bottom_d|=0xFF000000; + } + ((DWORD*)db)[x]=ske_Blend(bottom_d,top_d,alpha); + } + bb+=vstep_b; + tb+=vstep_t; + bmb+=vstep_bm; + tmb+=vstep_tm; + db+=vstep_d; + } + } + if (!bmp_bottom.bmBits) free(BottomBuffer); + if (!bmp_top.bmBits) free(TopBuffer); + if (!bmp_bottom_mask.bmBits) free(BottomMaskBuffer); + if (!bmp_top_mask.bmBits) free(TopMaskBuffer); + } + else + { + ske_DrawIconEx(tempDC,0,0,hBottom,16,16,0,NULL,DI_NORMAL); + ske_DrawIconEx(tempDC,0,0,hTop,16,16,0,NULL,DI_NORMAL|(alpha<<24)); + } + DeleteObject(iciBottom.hbmColor); + DeleteObject(iciTop.hbmColor); + DeleteObject(iciBottom.hbmMask); + DeleteObject(iciTop.hbmMask); + + SelectObject(tempDC,oImage); + DeleteDC(tempDC); + { + //BYTE *p=malloc(32); + //memset(p,0,32); + BYTE p[32] = {0}; + nMask=CreateBitmap(16,16,1,1,(void*)&p); + { + HDC tempDC2=CreateCompatibleDC(NULL); + HDC tempDC3=CreateCompatibleDC(NULL); + HBITMAP hbm=CreateCompatibleBitmap(tempDC3,16,16); + HBITMAP obmp=(HBITMAP)SelectObject(tempDC2,nMask); + HBITMAP obmp2=(HBITMAP)SelectObject(tempDC3,hbm); + DrawIconEx(tempDC2,0,0,hBottom,16,16,0,NULL,DI_MASK); + DrawIconEx(tempDC3,0,0,hTop,16,16,0,NULL,DI_MASK); + BitBlt(tempDC2,0,0,16,16,tempDC3,0,0,SRCAND); + SelectObject(tempDC2,obmp); + SelectObject(tempDC3,obmp2); + DeleteObject(hbm); + DeleteDC(tempDC2); + DeleteDC(tempDC3); + } + iNew.fIcon=TRUE; + iNew.hbmColor=nImage; + iNew.hbmMask=nMask; + res=CreateIconIndirect(&iNew); + DeleteObject(nImage); + DeleteObject(nMask); + } + return res; +} + +#define NEWJOINEDSTR( destination, first, separator, last) \ + destination=(char*)alloca(strlen(first)+strlen(separator)+strlen(last)+1); \ + if (destination) { \ + *destination='\0'; \ + strcat(destination,first); \ + strcat(destination,separator); \ + strcat(destination,last); \ + } + +#define SKINSETSECTION "SkinnedSettings" + +BOOL SkinDBGetContactSetting(HANDLE hContact, const char* szSection, const char*szKey, DBVARIANT * retdbv, BOOL * bSkined ) +{ + if (!hContact) { //only for not contact settings + char * szSkinKey; + NEWJOINEDSTR(szSkinKey,szSection,"@",szKey); + if ( !ModernGetSetting(hContact, SKINSETSECTION, szSkinKey, retdbv) ) { + if (bSkined) *bSkined=TRUE; + return FALSE; + } } + // not skinned + if (bSkined) bSkined=FALSE; + return ModernGetSetting(hContact, szSection, szKey, retdbv); +} + +BYTE SkinDBGetContactSettingByte(HANDLE hContact, const char* szSection, const char*szKey, BYTE bDefault) +{ + DBVARIANT dbv={0}; + BOOL bSkined=FALSE; + if ( !SkinDBGetContactSetting(hContact, szSection, szKey, &dbv, &bSkined)) { + if (dbv.type==DBVT_BYTE) + { + BYTE retVal=dbv.bVal; + ModernDBFreeVariant(&dbv); + return retVal; + } else { + ModernDBFreeVariant(&dbv); + if (!bSkined) return ModernGetSettingByte(hContact, szSection, szKey, bDefault); + } + } + return bDefault; +} + +WORD SkinDBGetContactSettingWord(HANDLE hContact, const char* szSection, const char*szKey, WORD wDefault) +{ + BOOL bSkined=FALSE; + DBVARIANT dbv={0}; + if ( !SkinDBGetContactSetting(hContact, szSection, szKey, &dbv, &bSkined)) { + if (dbv.type==DBVT_WORD) { + WORD retVal=dbv.wVal; + ModernDBFreeVariant(&dbv); + return retVal; + } else { + ModernDBFreeVariant(&dbv); + if (!bSkined) return ModernGetSettingWord(hContact, szSection, szKey, wDefault); + } + } + return wDefault; +} + +DWORD SkinDBGetContactSettingDword(HANDLE hContact, const char* szSection, const char*szKey, DWORD dwDefault) +{ + DBVARIANT dbv={0}; + BOOL bSkined=FALSE; + if ( !SkinDBGetContactSetting(hContact, szSection, szKey, &dbv, &bSkined)) { + if (dbv.type==DBVT_DWORD) { + DWORD retVal=dbv.dVal; + ModernDBFreeVariant(&dbv); + return retVal; + } else { + ModernDBFreeVariant(&dbv); + if (!bSkined) return ModernGetSettingDword(hContact, szSection, szKey, dwDefault); + } + } + return dwDefault; +} -- cgit v1.2.3