- improved ACS_TRANSPARENT and ACS_CENTER support

- added RLE8 incremental decompression
- each animation is now controlled by its own Windows thread
- added use of Critical Sections in the WM_PAINT handler.
This commit is contained in:
Jean-Claude Batista 2000-08-31 02:05:53 +00:00 committed by Alexandre Julliard
parent e75902a555
commit 8bdee6f329
1 changed files with 370 additions and 177 deletions

View File

@ -10,10 +10,9 @@
* Eric <ekohl@abo.rhein-zeitung.de> * Eric <ekohl@abo.rhein-zeitung.de>
* *
* TODO: * TODO:
* - correct RLE4 decompression
* - check for the 'rec ' list in some AVI files * - check for the 'rec ' list in some AVI files
* - implement some missing flags (ACS_TRANSPARENT) * - concurrent access to infoPtr
* - protection between service thread and wndproc messages handling
* concurrent access to infoPtr
*/ */
@ -62,19 +61,21 @@ typedef struct
LPVOID outdata; LPVOID outdata;
/* data for the background mechanism */ /* data for the background mechanism */
CRITICAL_SECTION cs; CRITICAL_SECTION cs;
HANDLE hService; HANDLE hThread;
UINT uTimer; UINT uTimer;
/* data for playing the file */ /* data for playing the file */
int nFromFrame; int nFromFrame;
int nToFrame; int nToFrame;
int nLoop; int nLoop;
int currFrame; int currFrame;
/* Background frame info*/ /* tranparency info*/
HBITMAP bkgFrameb; COLORREF transparentColor;
LPDWORD bkColor; HBRUSH hbrushBG;
} ANIMATE_INFO; } ANIMATE_INFO;
#define ANIMATE_GetInfoPtr(hWnd) ((ANIMATE_INFO *)GetWindowLongA(hWnd, 0)) #define ANIMATE_GetInfoPtr(hWnd) ((ANIMATE_INFO *)GetWindowLongA(hWnd, 0))
#define ANIMATE_COLOR_NONE 0xffffffff
HMODULE hModWinmm; HMODULE hModWinmm;
@ -114,8 +115,6 @@ static BOOL ANIMATE_LoadResA(ANIMATE_INFO *infoPtr, HINSTANCE hInst, LPSTR lpNam
return FALSE; return FALSE;
} }
infoPtr->bkgFrameb=(HBITMAP)NULL;
return TRUE; return TRUE;
} }
@ -137,9 +136,11 @@ static LRESULT ANIMATE_DoStop(ANIMATE_INFO *infoPtr)
EnterCriticalSection(&infoPtr->cs); EnterCriticalSection(&infoPtr->cs);
/* should stop playing */ /* should stop playing */
if (infoPtr->hService) { if (infoPtr->hThread)
SERVICE_Delete(infoPtr->hService); {
infoPtr->hService = 0; if (!TerminateThread(infoPtr->hThread,0))
WARN("could not destroy animation thread!\n");
infoPtr->hThread = 0;
} }
if (infoPtr->uTimer) { if (infoPtr->uTimer) {
KillTimer(infoPtr->hWnd, infoPtr->uTimer); KillTimer(infoPtr->hWnd, infoPtr->uTimer);
@ -159,11 +160,6 @@ static void ANIMATE_Free(ANIMATE_INFO *infoPtr)
if (infoPtr->hMMio) { if (infoPtr->hMMio) {
ANIMATE_DoStop(infoPtr); ANIMATE_DoStop(infoPtr);
infoPtr->fnmmioClose(infoPtr->hMMio, 0); infoPtr->fnmmioClose(infoPtr->hMMio, 0);
if (infoPtr->bkgFrameb) {
DeleteObject(infoPtr->bkgFrameb);
infoPtr->bkgFrameb=(HBITMAP)NULL;
infoPtr->bkColor=NULL;
}
if (infoPtr->hRes) { if (infoPtr->hRes) {
FreeResource(infoPtr->hRes); FreeResource(infoPtr->hRes);
infoPtr->hRes = 0; infoPtr->hRes = 0;
@ -184,141 +180,277 @@ static void ANIMATE_Free(ANIMATE_INFO *infoPtr)
HeapFree(GetProcessHeap(), 0, infoPtr->outbih); HeapFree(GetProcessHeap(), 0, infoPtr->outbih);
infoPtr->outbih = NULL; infoPtr->outbih = NULL;
} }
if( infoPtr->indata )
{
HeapFree(GetProcessHeap(), 0, infoPtr->indata); HeapFree(GetProcessHeap(), 0, infoPtr->indata);
infoPtr->indata = NULL;
}
if( infoPtr->outdata )
{
HeapFree(GetProcessHeap(), 0, infoPtr->outdata); HeapFree(GetProcessHeap(), 0, infoPtr->outdata);
infoPtr->outdata = NULL;
}
infoPtr->indata = infoPtr->outdata = NULL; infoPtr->indata = infoPtr->outdata = NULL;
infoPtr->hWnd = 0; infoPtr->hWnd = 0;
infoPtr->hMMio = 0; infoPtr->hMMio = 0;
memset(&infoPtr->mah, 0, sizeof(infoPtr->mah)); memset(&infoPtr->mah, 0, sizeof(infoPtr->mah));
memset(&infoPtr->ash, 0, sizeof(infoPtr->ash)); memset(&infoPtr->ash, 0, sizeof(infoPtr->ash));
infoPtr->nFromFrame = infoPtr->nToFrame = infoPtr->nLoop = infoPtr->currFrame = 0; infoPtr->nFromFrame = infoPtr->nToFrame = infoPtr->nLoop = infoPtr->currFrame = 0;
} }
infoPtr->transparentColor = ANIMATE_COLOR_NONE;
} }
/***********************************************************************
* ANIMATE_Expand_RLE8
*
* Decompresses an 8-bit compressed frame over previous frame
*
*/
enum Rle8_EscapeCodes
{
RleEol = 0, /* End of line */
RleEnd = 1, /* End of bitmap */
RleDelta = 2 /* Delta */
};
static LRESULT ANIMATE_Expand_RLE8(BYTE* pDest, int nWidth, int nHeight, BYTE* pSource)
{
int x; /* X-positon on each line. Increases. */
int line; /* Line #. Increases */
BYTE *pOut; /* current position in destination buffer */
BYTE length; /* The length of a run */
BYTE color_index; /* index for current pixel */
BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
int bEndOfBitmap=0;
/* image width including byte padding */
int nStride = ((( nWidth - 1 ) >> 2) + 1 ) << 2;
if (nHeight < 1 || nWidth < 1 || nStride < 1 || !pSource || !pDest)
return FALSE;
x = 0;
line = 0;
pOut = pDest;
do
{
length = *pSource++;
/*
* If the length byte is not zero (which is the escape value),
* We have a run of length pixels all the same colour. The color
* index is stored next.
*
* If the length byte is zero, we need to read the next byte to
* know what to do.
*/
if (length != 0)
{
/*
* [Run-Length] Encoded mode
*/
color_index = (*pSource++); /* Get the color index. */
while (length-- && x < nWidth)
{
*pOut++=color_index;
x++;
}
} else
{
/*
* Escape codes or absolute sequence
*/
escape_code = (*pSource++);
switch (escape_code)
{
case RleEol: /* =0, end of line */
{
x = 0;
line++;
pOut = pDest + nStride * line;
break;
}
case RleEnd: /* =1, end of bitmap */
{
bEndOfBitmap=TRUE;
line=nHeight; /* exit from loop. */
break;
}
case RleDelta: /* =2, a delta */
{
x += (*pSource++);
line += (*pSource++);
if (line >= nHeight || x >= nWidth)
{
WARN("Delta out of bounds\n");
line = nHeight;
}
pOut = pDest + (line * nStride) + x;
break;
}
default: /* >2, absolute mode */
{
length = escape_code;
while (length--)
{
color_index = (*pSource++);
if (x < nWidth)
{
*pOut++=color_index;
x++;
}
}
if (escape_code & 1)
pSource++; /* Throw away the pad byte. */
break;
}
} /* switch (escape_code) */
} /* process either an encoded sequence or an escape sequence */
/* We expect to come here more than once per line. */
} while (line < nHeight); /* Do this until the bitmap is filled */
if ( !bEndOfBitmap )
{
TRACE("Reached end of bitmap without a EndOfBitmap code\n");
}
return TRUE;
}
static void ANIMATE_TransparentBlt(ANIMATE_INFO* infoPtr, HDC hdcDest, HDC hdcSource)
{
HDC hdcMask;
HBITMAP hbmMask;
HBITMAP hbmOld;
/* create a transparency mask */
hdcMask = CreateCompatibleDC(hdcDest);
hbmMask = CreateBitmap(infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, 1,1,NULL);
hbmOld = SelectObject(hdcMask, hbmMask);
SetBkColor(hdcSource,infoPtr->transparentColor);
BitBlt(hdcMask,0,0,infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,hdcSource,0,0,SRCCOPY);
/* mask the source bitmap */
SetBkColor(hdcSource, RGB(0,0,0));
SetTextColor(hdcSource, RGB(255,255,255));
BitBlt(hdcSource, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND);
/* mask the destination bitmap */
SetBkColor(hdcDest, RGB(255,255,255));
SetTextColor(hdcDest, RGB(0,0,0));
BitBlt(hdcDest, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND);
/* combine source and destination */
BitBlt(hdcDest,0,0,infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,hdcSource,0,0,SRCPAINT);
SelectObject(hdcMask, hbmOld);
DeleteObject(hbmMask);
DeleteDC(hdcMask);
}
static LRESULT ANIMATE_PaintFrame(ANIMATE_INFO* infoPtr, HDC hDC) static LRESULT ANIMATE_PaintFrame(ANIMATE_INFO* infoPtr, HDC hDC)
{ {
void* pBitmapData = NULL;
LPBITMAPINFO pBitmapInfo = NULL;
HDC hdcMem;
HBITMAP hbmNew;
HBITMAP hbmOld;
int nOffsetX = 0;
int nOffsetY = 0;
int nWidth;
int nHeight;
if (!hDC || !infoPtr->inbih) if (!hDC || !infoPtr->inbih)
return TRUE; return TRUE;
if (infoPtr->hic){
if (GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_TRANSPARENT){
FIXME("TRANSPARENCY NOT SUPPORTED(NOT TESTED) FOR COMPRESSED IMAGE\n");
}
StretchDIBits(hDC, 0, 0, infoPtr->outbih->biWidth, infoPtr->outbih->biHeight,
0, 0, infoPtr->outbih->biWidth, infoPtr->outbih->biHeight,
infoPtr->outdata, (LPBITMAPINFO)infoPtr->outbih, DIB_RGB_COLORS,
SRCCOPY);
}
else{
if (GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_TRANSPARENT){
HBITMAP hbmMem, hbmMem2,hbmMem3;
HDC hdcSrc, hdcMask, hdcMem;
hdcSrc = CreateCompatibleDC(hDC); if (infoPtr->hic ||
hdcMask = CreateCompatibleDC(hDC); /* put this once correct RLE4 decompression is implemented */
hdcMem = CreateCompatibleDC(hDC); /* infoPtr->inbih->biCompression == BI_RLE4 || */
infoPtr->inbih->biCompression == BI_RLE8 )
/* create a Black and white bitmap */
hbmMem = CreateCompatibleBitmap( hDC,infoPtr->inbih->biWidth,infoPtr->inbih->biHeight);
hbmMem2 = CreateBitmap(infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, 1, 1, NULL);
hbmMem3 = CreateCompatibleBitmap( hDC,infoPtr->inbih->biWidth,infoPtr->inbih->biHeight);
SelectObject( hdcSrc, hbmMem);
StretchDIBits(hdcSrc, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,
0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,
infoPtr->indata, (LPBITMAPINFO)infoPtr->inbih, DIB_RGB_COLORS,
SRCCOPY);
if (infoPtr->bkgFrameb==(HBITMAP)NULL)
{ {
infoPtr->bkgFrameb = CreateCompatibleBitmap( hDC,infoPtr->inbih->biWidth,infoPtr->inbih->biHeight); pBitmapData = infoPtr->outdata;
SelectObject( hdcMem, infoPtr->bkgFrameb); pBitmapInfo = (LPBITMAPINFO)infoPtr->outbih;
BitBlt(hdcMem, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hDC, 0, 0, SRCCOPY);
/* Get the transparent color from the first frame*/ nWidth = infoPtr->outbih->biWidth;
switch (infoPtr->inbih->biBitCount) { nHeight = infoPtr->outbih->biHeight;
case 1: }
case 4: else
/*FIXME: Not supported Yet.*/ {
break; pBitmapData = infoPtr->indata;
case 8: pBitmapInfo = (LPBITMAPINFO)infoPtr->inbih;
infoPtr->bkColor = (LPVOID)((LPSTR)infoPtr->inbih + (WORD)(((LPBITMAPINFO)infoPtr->inbih)->bmiHeader.biSize));
break; nWidth = infoPtr->inbih->biWidth;
case 16: nHeight = infoPtr->inbih->biHeight;
case 24:
case 32:
infoPtr->bkColor = (LPVOID)GetPixel(hdcSrc, 0, 0);
/*FIXME:Has not been test with more than 8bpp, errors are possible*/
break;
} }
} if (infoPtr->inbih->biCompression == BI_RLE8)
/* Need the copy of the original destination HDC*/ ANIMATE_Expand_RLE8(pBitmapData, nWidth, nHeight, infoPtr->indata);
SelectObject( hdcSrc, infoPtr->bkgFrameb);
SelectObject( hdcMem, hbmMem3);
BitBlt(hdcMem, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcSrc, 0, 0, SRCCOPY);
SelectObject( hdcSrc, hbmMem); if (infoPtr->inbih->biCompression == BI_RLE4)
SelectObject( hdcMask, hbmMem2); FIXME("correct RLE4 decompression not implemented yet (no samples available)\n");
/*Windows converts a color source into monochrome when the destination is hdcMem = CreateCompatibleDC(hDC);
monochrome. In this situation, all pixels in the color bitmap that are the same color hbmNew = CreateCompatibleBitmap(hDC,nWidth, nHeight);
as the background color become 1s, and all the other pixels are converted to 0s. */ hbmOld = SelectObject(hdcMem, hbmNew);
/* Set the transparent color from the first frame*/ StretchDIBits(hdcMem, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,
switch (infoPtr->inbih->biBitCount) {
case 1:
case 4:
/*FIXME: Not supported Yet.*/
break;
case 8:
SetBkColor(hdcSrc, infoPtr->bkColor[(((BYTE*)infoPtr->indata)[0])]);
break;
case 16:
case 24:
case 32:
SetBkColor(hdcSrc, (COLORREF)infoPtr->bkColor);
break;
}
BitBlt(hdcMask, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcSrc, 0, 0, SRCCOPY);
/*During a blt operation with a color destination, a monochrome source bitmap
(and/or a brush when applicable) is converted to color on the fly before the
actual ROP is carried out on the bits. The 0 (black) pixels in the monochrome
bitmap are converted to the destination's text (foreground) color, and the 1
(white) pixels are converted to the background color. */
SetBkColor(hdcSrc, RGB(0,0,0)); /* 1s --> black (0x000000)*/
SetTextColor(hdcSrc, RGB(255,255,255)); /* 0s --> white (0xFFFFFF)*/
BitBlt(hdcSrc, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND);
SetBkColor(hdcMem, RGB(255,255,255)); /* 0s --> white (0xFFFFFF) */
SetTextColor(hdcMem, RGB(0,0,0)); /* 1s --> black (0x000000) */
BitBlt(hdcMem, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND);
BitBlt(hdcMem, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcSrc, 0, 0, SRCPAINT);
BitBlt(hDC, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMem, 0, 0, SRCCOPY);
DeleteDC(hdcMem);
DeleteDC(hdcSrc);
DeleteDC(hdcMask);
DeleteObject(hbmMem);
DeleteObject(hbmMem2);
DeleteObject(hbmMem3);
}
else{
StretchDIBits(hDC, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,
0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,
infoPtr->indata, (LPBITMAPINFO)infoPtr->inbih, DIB_RGB_COLORS, pBitmapData, (LPBITMAPINFO)pBitmapInfo, DIB_RGB_COLORS,
SRCCOPY); SRCCOPY);
}
/*
* 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)
{
infoPtr->transparentColor = GetPixel(hdcMem,0,0);
} }
if(GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_TRANSPARENT)
{
HDC hdcFinal = CreateCompatibleDC(hDC);
HBITMAP hbmFinal = CreateCompatibleBitmap(hDC,nWidth, nHeight);
HBITMAP hbmOld2 = SelectObject(hdcFinal, hbmFinal);
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = nWidth;
rect.bottom = nHeight;
if(!infoPtr->hbrushBG)
infoPtr->hbrushBG = GetCurrentObject(hDC, OBJ_BRUSH);
FillRect(hdcFinal, &rect, infoPtr->hbrushBG);
ANIMATE_TransparentBlt(infoPtr, hdcFinal, hdcMem);
SelectObject(hdcFinal, hbmOld2);
SelectObject(hdcMem, hbmFinal);
DeleteDC(hdcFinal);
DeleteObject(hbmNew);
hbmNew=hbmFinal;
}
if (GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_CENTER)
{
RECT rect;
GetWindowRect(infoPtr->hWnd, &rect);
nOffsetX = ((rect.right - rect.left) - nWidth)/2;
nOffsetY = ((rect.bottom - rect.top) - nHeight)/2;
}
BitBlt(hDC, nOffsetX, nOffsetY, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
DeleteObject(hbmNew);
return TRUE; return TRUE;
} }
@ -359,13 +491,34 @@ static LRESULT ANIMATE_DrawFrame(ANIMATE_INFO* infoPtr)
return TRUE; return TRUE;
} }
static void CALLBACK ANIMATE_ServiceCallback(ULONG_PTR ptr_) static DWORD CALLBACK ANIMATE_AnimationThread(LPVOID ptr_)
{ {
ANIMATE_INFO* infoPtr = (ANIMATE_INFO*)ptr_; ANIMATE_INFO* infoPtr = (ANIMATE_INFO*)ptr_;
HDC hDC;
if(!infoPtr)
{
WARN("animation structure undefined!\n");
return FALSE;
}
while(1)
{
if(GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_TRANSPARENT)
{
hDC = GetDC(infoPtr->hWnd);
infoPtr->hbrushBG = SendMessageA(GetParent(infoPtr->hWnd),WM_CTLCOLORSTATIC,hDC, infoPtr->hWnd);
ReleaseDC(infoPtr->hWnd,hDC);
}
EnterCriticalSection(&infoPtr->cs); EnterCriticalSection(&infoPtr->cs);
ANIMATE_DrawFrame(infoPtr); ANIMATE_DrawFrame(infoPtr);
LeaveCriticalSection(&infoPtr->cs); LeaveCriticalSection(&infoPtr->cs);
/* time is in microseconds, we should convert it to milliseconds */
Sleep((infoPtr->mah.dwMicroSecPerFrame+500)/1000);
}
return TRUE;
} }
static LRESULT ANIMATE_Play(HWND hWnd, WPARAM wParam, LPARAM lParam) static LRESULT ANIMATE_Play(HWND hWnd, WPARAM wParam, LPARAM lParam)
@ -376,7 +529,7 @@ static LRESULT ANIMATE_Play(HWND hWnd, WPARAM wParam, LPARAM lParam)
if (!infoPtr->hMMio) if (!infoPtr->hMMio)
return FALSE; return FALSE;
if (infoPtr->hService || infoPtr->uTimer) { if (infoPtr->hThread || infoPtr->uTimer) {
FIXME("Already playing ? what should I do ??\n"); FIXME("Already playing ? what should I do ??\n");
ANIMATE_DoStop(infoPtr); ANIMATE_DoStop(infoPtr);
} }
@ -402,10 +555,16 @@ static LRESULT ANIMATE_Play(HWND hWnd, WPARAM wParam, LPARAM lParam)
/* create a timer to display AVI */ /* create a timer to display AVI */
infoPtr->uTimer = SetTimer(hWnd, 1, infoPtr->mah.dwMicroSecPerFrame / 1000, NULL); infoPtr->uTimer = SetTimer(hWnd, 1, infoPtr->mah.dwMicroSecPerFrame / 1000, NULL);
} else { } else {
TRACE("Using the service thread\n"); DWORD threadID;
/* time is in µs */
infoPtr->hService = SERVICE_AddTimer(infoPtr->mah.dwMicroSecPerFrame / 1000, TRACE("Using an animation thread\n");
ANIMATE_ServiceCallback, (DWORD)infoPtr); infoPtr->hThread = CreateThread(0,0,ANIMATE_AnimationThread,(LPVOID)infoPtr,0,0 &threadID);
if(!infoPtr->hThread)
{
ERR("Could not create animation thread!\n");
return FALSE;
}
} }
ANIMATE_Notify(infoPtr, ACN_START); ANIMATE_Notify(infoPtr, ACN_START);
@ -586,11 +745,52 @@ static BOOL ANIMATE_GetAviCodec(ANIMATE_INFO *infoPtr)
DWORD outSize; DWORD outSize;
/* check uncompressed AVI */ /* check uncompressed AVI */
if (infoPtr->ash.fccHandler == mmioFOURCC('D', 'I', 'B', ' ') || if (infoPtr->ash.fccHandler == mmioFOURCC('D', 'I', 'B', ' ')) {
infoPtr->ash.fccHandler == mmioFOURCC('R', 'L', 'E', ' ')) {
infoPtr->hic = 0; infoPtr->hic = 0;
return TRUE; return TRUE;
} }
else if (infoPtr->ash.fccHandler == mmioFOURCC('R', 'L', 'E', ' '))
{
int nStride = 0;
int frameBufferSize;
int sizebih=sizeof(BITMAPINFOHEADER) + infoPtr->inbih->biClrUsed *sizeof(RGBQUAD);
if(infoPtr->inbih->biCompression == BI_RLE8)
nStride = (((( infoPtr->inbih->biWidth - 1 ) >> 2) + 1 ) << 2);
else if(infoPtr->inbih->biCompression == BI_RLE4)
nStride = (((( infoPtr->inbih->biWidth - 1 ) >> 3) + 1 ) << 2);
else
{
ERR("Image compression format unknown\n");
return FALSE;
}
frameBufferSize = infoPtr->inbih->biHeight * nStride;
infoPtr->hic = 0;
infoPtr->outbih = HeapAlloc(GetProcessHeap(),0, sizebih);
if(!infoPtr->outbih)
{
ERR("out of memory!\n");
return FALSE;
}
infoPtr->outdata = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, frameBufferSize);
if(!infoPtr->outdata)
{
HeapFree(GetProcessHeap(),0,infoPtr->outbih);
infoPtr->outbih = 0;
ERR("out of memory!\n");
return FALSE;
}
/* create a BITMAPINFO header for the uncompressed bitmap */
memcpy(infoPtr->outbih, infoPtr->inbih, sizebih);
infoPtr->outbih->biCompression = BI_RGB;
infoPtr->outbih->biSizeImage = frameBufferSize;
return TRUE;
}
/* try to get a decompressor for that type */ /* try to get a decompressor for that type */
infoPtr->hic = (infoPtr->fnICOpen)(ICTYPE_VIDEO, infoPtr->hic = (infoPtr->fnICOpen)(ICTYPE_VIDEO,
@ -633,23 +833,6 @@ static BOOL ANIMATE_GetAviCodec(ANIMATE_INFO *infoPtr)
return TRUE; return TRUE;
} }
static void ANIMATE_Center(ANIMATE_INFO *infoPtr)
{
int x,y,dx,dy;
RECT Rect;
HWND hWnd=infoPtr->hWnd;
HWND hWndParent=GetWindowLongA(hWnd, GWL_HWNDPARENT);
if (!hWndParent || !GetWindowRect(hWndParent, &Rect)) return;
dx=Rect.right-Rect.left+1;
dy=Rect.bottom-Rect.top+1;
x=infoPtr->mah.dwWidth < dx ? (dx-infoPtr->mah.dwWidth) >> 1 : 0;
y=infoPtr->mah.dwHeight < dy ? (dy-infoPtr->mah.dwHeight) >> 1 : 0;
MoveWindow(hWnd, x, y, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight, TRUE);
}
static LRESULT ANIMATE_OpenA(HWND hWnd, WPARAM wParam, LPARAM lParam) static LRESULT ANIMATE_OpenA(HWND hWnd, WPARAM wParam, LPARAM lParam)
{ {
ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd); ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
@ -697,20 +880,11 @@ static LRESULT ANIMATE_OpenA(HWND hWnd, WPARAM wParam, LPARAM lParam)
return FALSE; return FALSE;
} }
if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) { if (!GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) {
ANIMATE_Center(infoPtr);
} else {
/* MoveWindow(hWnd, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight, FALSE);*/
SetWindowPos(hWnd, 0, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight, SetWindowPos(hWnd, 0, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER); SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
} }
if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) {
FIXME("ACS_TRANSPARENT: NIY\n");
}
if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_AUTOPLAY) { if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_AUTOPLAY) {
return ANIMATE_Play(hWnd, -1, (LPARAM)MAKELONG(0, infoPtr->mah.dwTotalFrames-1)); return ANIMATE_Play(hWnd, -1, (LPARAM)MAKELONG(0, infoPtr->mah.dwTotalFrames-1));
} }
@ -760,7 +934,7 @@ static LRESULT ANIMATE_Create(HWND hWnd, WPARAM wParam, LPARAM lParam)
/* store crossref hWnd <-> info structure */ /* store crossref hWnd <-> info structure */
SetWindowLongA(hWnd, 0, (DWORD)infoPtr); SetWindowLongA(hWnd, 0, (DWORD)infoPtr);
infoPtr->hWnd = hWnd; infoPtr->hWnd = hWnd;
infoPtr->transparentColor = ANIMATE_COLOR_NONE;
hModWinmm = LoadLibraryA("WINMM"); hModWinmm = LoadLibraryA("WINMM");
infoPtr->fnmmioOpenA = (void*)GetProcAddress(hModWinmm, "mmioOpenA"); infoPtr->fnmmioOpenA = (void*)GetProcAddress(hModWinmm, "mmioOpenA");
@ -796,29 +970,22 @@ static LRESULT ANIMATE_Destroy(HWND hWnd, WPARAM wParam, LPARAM lParam)
static LRESULT ANIMATE_EraseBackground(HWND hWnd, WPARAM wParam, LPARAM lParam) static LRESULT ANIMATE_EraseBackground(HWND hWnd, WPARAM wParam, LPARAM lParam)
{ {
RECT rect; RECT rect;
HBRUSH hBrush = 0;
if(GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT)
{
hBrush = SendMessageA(GetParent(hWnd),WM_CTLCOLORSTATIC,(HDC)wParam, hWnd);
}
GetClientRect(hWnd, &rect); GetClientRect(hWnd, &rect);
#if 0 FillRect((HDC)wParam, &rect, hBrush ? hBrush : GetCurrentObject((HDC)wParam, OBJ_BRUSH));
HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
FillRect((HDC)wParam, &rect, hBrush);
DeleteObject(hBrush);
#else
FillRect((HDC)wParam, &rect, GetSysColorBrush(COLOR_WINDOW));
#endif
return TRUE; return TRUE;
} }
static LRESULT WINAPI ANIMATE_Size(HWND hWnd, WPARAM wParam, LPARAM lParam) static LRESULT WINAPI ANIMATE_Size(HWND hWnd, WPARAM wParam, LPARAM lParam)
{ {
ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd);
if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) { if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) {
if (infoPtr->hMMio) {
/* centers the animation in the control, invalidates the control
*/
ANIMATE_Center(infoPtr);
}
InvalidateRect(hWnd, NULL, TRUE); InvalidateRect(hWnd, NULL, TRUE);
} }
return TRUE; return TRUE;
@ -861,6 +1028,11 @@ static LRESULT WINAPI ANIMATE_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP
/* case WM_STYLECHANGED: FIXME shall we do something ?? */ /* case WM_STYLECHANGED: FIXME shall we do something ?? */
case WM_TIMER: case WM_TIMER:
if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT)
{
ANIMATE_INFO* infoPtr = ANIMATE_GetInfoPtr(hWnd);
infoPtr->hbrushBG = SendMessageA(GetParent(hWnd),WM_CTLCOLORSTATIC,(HDC)wParam, hWnd);
}
return ANIMATE_DrawFrame(ANIMATE_GetInfoPtr(hWnd)); return ANIMATE_DrawFrame(ANIMATE_GetInfoPtr(hWnd));
case WM_CLOSE: case WM_CLOSE:
@ -868,14 +1040,35 @@ static LRESULT WINAPI ANIMATE_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP
return TRUE; return TRUE;
case WM_PAINT: case WM_PAINT:
if (wParam) { {
ANIMATE_PaintFrame(ANIMATE_GetInfoPtr(hWnd), (HDC)wParam); ANIMATE_INFO* infoPtr = ANIMATE_GetInfoPtr(hWnd);
} else {
/* the animation isn't playing, don't paint */
if(!infoPtr->uTimer && !infoPtr->hThread)
break;
if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT)
infoPtr->hbrushBG = SendMessageA(GetParent(hWnd), WM_CTLCOLORSTATIC,
(HDC)wParam, hWnd);
if (wParam)
{
EnterCriticalSection(&infoPtr->cs);
ANIMATE_PaintFrame(infoPtr, (HDC)wParam);
LeaveCriticalSection(&infoPtr->cs);
}
else
{
PAINTSTRUCT ps; PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps); HDC hDC = BeginPaint(hWnd, &ps);
ANIMATE_PaintFrame(ANIMATE_GetInfoPtr(hWnd), hDC);
EnterCriticalSection(&infoPtr->cs);
ANIMATE_PaintFrame(infoPtr, hDC);
LeaveCriticalSection(&infoPtr->cs);
EndPaint(hWnd, &ps); EndPaint(hWnd, &ps);
} }
}
break; break;
case WM_SIZE: case WM_SIZE: