Index: dll/win32/comctl32/animate.c =================================================================== --- dll/win32/comctl32/animate.c (revision 39857) +++ dll/win32/comctl32/animate.c (working copy) @@ -45,7 +45,14 @@ #include "mmsystem.h" #include "comctl32.h" #include "wine/debug.h" +#include +BOOL WINAPI GdiTransparentBlt( + HDC hdcDst, int xDst, int yDst, int wDst, int hDst, + HDC hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc, + UINT crTransparent); + + WINE_DEFAULT_DEBUG_CHANNEL(animate); static struct { @@ -89,6 +96,8 @@ COLORREF transparentColor; HBRUSH hbrushBG; HBITMAP hbmPrevFrame; + int prevFrame; + int controlFrame; } ANIMATE_INFO; #define ANIMATE_COLOR_NONE 0xffffffff @@ -222,6 +231,7 @@ infoPtr->transparentColor = ANIMATE_COLOR_NONE; } +#if 0 // Full analog GdiTransparentBlt static void ANIMATE_TransparentBlt(ANIMATE_INFO const *infoPtr, HDC hdcDest, HDC hdcSource) { HDC hdcMask; @@ -253,20 +263,33 @@ DeleteObject(hbmMask); DeleteDC(hdcMask); } +#endif -static BOOL ANIMATE_PaintFrame(ANIMATE_INFO* infoPtr, HDC hDC) +static BOOL ANIMATE_PrepareFrame(ANIMATE_INFO* infoPtr, HDC hDC, int currFrame) { void const *pBitmapData; BITMAPINFO const *pBitmapInfo; HDC hdcMem; HBITMAP hbmOld; - int nOffsetX = 0; - int nOffsetY = 0; int nWidth; int nHeight; + if (currFrame < 0 || currFrame > infoPtr->nToFrame) + return FALSE; + + mmioSeek(infoPtr->hMMio, infoPtr->lpIndex[currFrame], SEEK_SET); + mmioRead(infoPtr->hMMio, infoPtr->indata, infoPtr->ash.dwSuggestedBufferSize); + + if (infoPtr->hic && + fnIC.fnICDecompress(infoPtr->hic, 0, infoPtr->inbih, infoPtr->indata, + infoPtr->outbih, infoPtr->outdata) != ICERR_OK) + { + WARN("Decompression error\n"); + return FALSE; + } + if (!hDC || !infoPtr->inbih) - return TRUE; + return FALSE; if (infoPtr->hic ) { @@ -287,29 +310,95 @@ if(!infoPtr->hbmPrevFrame) { - infoPtr->hbmPrevFrame=CreateCompatibleBitmap(hDC, nWidth,nHeight ); + infoPtr->hbmPrevFrame = CreateCompatibleBitmap(hDC, nWidth,nHeight ); } hdcMem = CreateCompatibleDC(hDC); hbmOld = SelectObject(hdcMem, infoPtr->hbmPrevFrame); - SetDIBits(hdcMem, infoPtr->hbmPrevFrame, 0, nHeight, pBitmapData, pBitmapInfo, DIB_RGB_COLORS); + if (currFrame == 0 || infoPtr->prevFrame == -1) + { + //First or control frame full drawing + SetDIBits(hdcMem, infoPtr->hbmPrevFrame, 0, nHeight, pBitmapData, pBitmapInfo, DIB_RGB_COLORS); + } + else + { + HDC hdcFrame = CreateCompatibleDC(hDC); + HBITMAP hbmFrame = CreateCompatibleBitmap(hDC,nWidth, nHeight); + HBITMAP hbmOldFrame = SelectObject(hdcFrame, hbmFrame); - /* - * we need to get the transparent color even without ACS_TRANSPARENT, - * because the style can be changed later on and the color should always - * be obtained in the first frame - */ - if(infoPtr->transparentColor == ANIMATE_COLOR_NONE) + SetDIBits(hdcFrame, hbmFrame, 0, nHeight, pBitmapData, pBitmapInfo, DIB_RGB_COLORS); + + //Union old and curr surface. Next frame uses only moved object. + GdiTransparentBlt(hdcMem, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, + hdcFrame, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, 0); + + SelectObject(hdcFrame, hbmOldFrame); + DeleteObject(hbmFrame); + DeleteDC(hdcFrame); + } + + infoPtr->prevFrame = currFrame; + + SelectObject(hdcMem, hbmOld); + DeleteDC(hdcMem); + return TRUE; +} + +static BOOL ANIMATE_PaintFrame(ANIMATE_INFO* infoPtr, HDC hDC) +{ + HDC hdcMem; + HBITMAP hbmOld; + int nOffsetX = 0; + int nOffsetY = 0; + int nWidth; + int nHeight; + + if (!infoPtr->hbmPrevFrame || + infoPtr->currFrame > infoPtr->prevFrame + infoPtr->controlFrame || + infoPtr->currFrame < infoPtr->prevFrame) { - infoPtr->transparentColor = GetPixel(hdcMem,0,0); + INT i, iStart; + infoPtr->prevFrame = -1; + iStart = infoPtr->currFrame - infoPtr->controlFrame; + for (i=(iStart < 0 ? 0 : iStart);i <= infoPtr->currFrame;i++) + ANIMATE_PrepareFrame(infoPtr, hDC, i); } + + if (infoPtr->prevFrame != infoPtr->currFrame) + ANIMATE_PrepareFrame(infoPtr, hDC, infoPtr->currFrame); + if (!hDC || !infoPtr->inbih) + return TRUE; + + if (infoPtr->hic ) + { + nWidth = infoPtr->outbih->biWidth; + nHeight = infoPtr->outbih->biHeight; + } + else + { + nWidth = infoPtr->inbih->biWidth; + nHeight = infoPtr->inbih->biHeight; + } + + hdcMem = CreateCompatibleDC(hDC); + hbmOld = SelectObject(hdcMem, infoPtr->hbmPrevFrame); + + if (infoPtr->dwStyle & ACS_CENTER) + { + RECT rect; + + GetWindowRect(infoPtr->hwndSelf, &rect); + nOffsetX = ((rect.right - rect.left) - nWidth)/2; + nOffsetY = ((rect.bottom - rect.top) - nHeight)/2; + } + if(infoPtr->dwStyle & ACS_TRANSPARENT) { - HDC hdcFinal = CreateCompatibleDC(hDC); - HBITMAP hbmFinal = CreateCompatibleBitmap(hDC,nWidth, nHeight); - HBITMAP hbmOld2 = SelectObject(hdcFinal, hbmFinal); + HDC hdcMem2 = CreateCompatibleDC(hDC); + HBITMAP hbmMem2 = CreateCompatibleBitmap(hDC,nWidth, nHeight); + HBITMAP hbmOldMem2 = SelectObject(hdcMem2, hbmMem2); RECT rect; rect.left = 0; @@ -320,25 +409,21 @@ if(!infoPtr->hbrushBG) infoPtr->hbrushBG = GetCurrentObject(hDC, OBJ_BRUSH); - FillRect(hdcFinal, &rect, infoPtr->hbrushBG); - ANIMATE_TransparentBlt(infoPtr, hdcFinal, hdcMem); + FillRect(hdcMem2, &rect, infoPtr->hbrushBG); - SelectObject(hdcFinal, hbmOld2); - SelectObject(hdcMem, hbmFinal); - DeleteDC(hdcFinal); - DeleteObject(infoPtr->hbmPrevFrame); - infoPtr->hbmPrevFrame = hbmFinal; - } + GdiTransparentBlt(hdcMem2, nOffsetX, nOffsetY, nWidth, nHeight, + hdcMem, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, infoPtr->transparentColor); - if (infoPtr->dwStyle & ACS_CENTER) - { - RECT rect; + BitBlt(hDC, nOffsetX, nOffsetY, nWidth, nHeight, hdcMem2, 0, 0, SRCCOPY); - GetWindowRect(infoPtr->hwndSelf, &rect); - nOffsetX = ((rect.right - rect.left) - nWidth)/2; - nOffsetY = ((rect.bottom - rect.top) - nHeight)/2; + SelectObject(hdcMem2, hbmOldMem2); + DeleteObject(hbmMem2); + DeleteDC(hdcMem2); } - BitBlt(hDC, nOffsetX, nOffsetY, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY); + else + { + BitBlt(hDC, nOffsetX, nOffsetY, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY); + } SelectObject(hdcMem, hbmOld); DeleteDC(hdcMem); @@ -349,16 +434,6 @@ { TRACE("Drawing frame %d (loop %d)\n", infoPtr->currFrame, infoPtr->nLoop); - mmioSeek(infoPtr->hMMio, infoPtr->lpIndex[infoPtr->currFrame], SEEK_SET); - mmioRead(infoPtr->hMMio, infoPtr->indata, infoPtr->ash.dwSuggestedBufferSize); - - if (infoPtr->hic && - fnIC.fnICDecompress(infoPtr->hic, 0, infoPtr->inbih, infoPtr->indata, - infoPtr->outbih, infoPtr->outdata) != ICERR_OK) { - WARN("Decompression error\n"); - return FALSE; - } - ANIMATE_PaintFrame(infoPtr, hDC); if (infoPtr->currFrame++ >= infoPtr->nToFrame) { @@ -756,6 +831,47 @@ /* native looks at the top left pixel of the first frame here too. */ infoPtr->hbrushBG = (HBRUSH)SendMessageW(infoPtr->hwndNotify, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)infoPtr->hwndSelf); + + /* + * we need to get the transparent color even without ACS_TRANSPARENT, + * because the style can be changed later on and the color should always + * be obtained in the first frame + */ + mmioSeek(infoPtr->hMMio, infoPtr->lpIndex[infoPtr->nFromFrame], SEEK_SET); + mmioRead(infoPtr->hMMio, infoPtr->indata, infoPtr->ash.dwSuggestedBufferSize); + if (infoPtr->hic && + fnIC.fnICDecompress(infoPtr->hic, 0, infoPtr->inbih, infoPtr->indata, + infoPtr->outbih, infoPtr->outdata) != ICERR_OK) { + WARN("Decompression error\n"); + return FALSE; + } + void const *pBitmapData; + BITMAPINFO const *pBitmapInfo; + int nWidth; + int nHeight; + if (infoPtr->hic ) + { + pBitmapData = infoPtr->outdata; + pBitmapInfo = (LPBITMAPINFO)infoPtr->outbih; + nWidth = infoPtr->outbih->biWidth; + nHeight = infoPtr->outbih->biHeight; + } + else + { + pBitmapData = infoPtr->indata; + pBitmapInfo = (LPBITMAPINFO)infoPtr->inbih; + nWidth = infoPtr->inbih->biWidth; + nHeight = infoPtr->inbih->biHeight; + } + HDC hdcFrame = CreateCompatibleDC(hdc); + HBITMAP hbmFrame = CreateCompatibleBitmap(hdc, nWidth, nHeight); + HBITMAP hbmOldFrame = SelectObject(hdcFrame, hbmFrame); + SetDIBits(hdcFrame, hbmFrame, 0, nHeight, pBitmapData, pBitmapInfo, DIB_RGB_COLORS); + infoPtr->transparentColor = GetPixel(hdcFrame,0,0); + SelectObject(hdcFrame, hbmOldFrame); + DeleteObject(hbmFrame); + DeleteDC(hdcFrame); + ReleaseDC(infoPtr->hwndSelf, hdc); if (!(infoPtr->dwStyle & ACS_CENTER)) @@ -827,6 +943,8 @@ infoPtr->transparentColor = ANIMATE_COLOR_NONE; infoPtr->hbmPrevFrame = 0; infoPtr->dwStyle = lpcs->style; + infoPtr->prevFrame = -1; + infoPtr->controlFrame = 100; TRACE("Animate style=0x%08x, parent=%p\n", infoPtr->dwStyle, infoPtr->hwndNotify);