/* * The user must be able to call AnimationStart and AnimationStop when this thread is being executed. */ void AnimationQueue() { struct LinkedList* _List = NULL; struct LnkLst_Node* _Itr = NULL; struct Animation* _Animation = NULL; int _Time = SDL_GetTicks(); while(_Itr != NULL) { _Animation = (struct Animation*) _Itr->Data; if(_Time - _Animation->LastFramePlay >= _Animation->Base->Frames[_Animation->CurrFrame].Speed) { AnimationNextFrame(_Animation, _Time); } _Itr = _Itr->Next; } _Itr = _List->Front; if(_List->Size == 0) return; SDL_LockMutex(g_AnimationLock); do { _Animation = (struct Animation*) _Itr->Data; DestroyAnimation(_Animation); LnkLstRemove(_List, _Itr); _Itr = _Itr->Next; } while(_Itr != NULL); SDL_UnlockMutex(g_AnimationLock); }
ANIMATION* CreateAnimationFromGIF89a (HDC hdc, MG_RWops* area) { unsigned char c; int ok = 0; MYBITMAP mybmp; GIFSCREEN GifScreen; IMAGEDESC ImageDesc; ANIMATION* anim; ANIMATIONFRAME* frame, *current = NULL; anim = calloc (1, sizeof (ANIMATION)); if (anim == NULL) return NULL; anim->time_unit = 1; if (ReadGIFGlobal (area, &GifScreen) < 0) goto error; anim->width = GifScreen.Width; anim->height = GifScreen.Height; if (GifScreen.Background >= 0) { anim->bk = GifScreen.ColorMap [GifScreen.Background]; anim->bk.a = 1; } else { anim->bk.r = anim->bk.g = anim->bk.b = 255; anim->bk.a = 0; } _MG_PRINTF ("EX_CTRL>GIF89a: Background: %d, %d, %d.\n", anim->bk.r, anim->bk.g, anim->bk.b); if ((ok = ReadOK (area, &c, 1)) == 0) { _MG_PRINTF ("EX_CTRL>GIF89a: EOF on image data\n"); goto error; } while (c != ';' && ok > 0) { switch (c) { case '!': if ( (ok = ReadOK (area, &c, 1)) == 0) { _MG_PRINTF ("EX_CTRL>GIF89a: EOF on image data\n"); goto error; } DoExtension (area, c, &GifScreen); _MG_PRINTF ("EX_CTRL>GIF89a: Extension info: %d, %d, %d, %d, %d, %d\n", GifScreen.Width, GifScreen.Height, GifScreen.AspectRatio, GifScreen.delayTime, GifScreen.disposal, GifScreen.transparent); break; case ',': if (ReadImageDesc (area, &ImageDesc, &GifScreen) < 0) { goto error; } else { if (ReadImage (area, &mybmp, &ImageDesc, &GifScreen, 0) < 0) goto error; } _MG_PRINTF ("EX_CTRL>GIF89a: Image Descriptor: %d, %d, %d, %d, %d\n", ImageDesc.Top, ImageDesc.Left, ImageDesc.Width, ImageDesc.Height, ImageDesc.haveColorMap); frame = (ANIMATIONFRAME*) calloc (1, sizeof (ANIMATIONFRAME)); if (!frame) goto error; else { frame->next = NULL; frame->disposal = GifScreen.disposal; frame->off_y = ImageDesc.Left; frame->off_x = ImageDesc.Top; frame->width = mybmp.w; frame->height = mybmp.h; frame->delay_time = (GifScreen.delayTime>10)?GifScreen.delayTime:10; _MG_PRINTF ("EX_CTRL>GIF89a: frame info: %d, %d, %d, %d\n", frame->off_x, frame->off_y, frame->delay_time, GifScreen.transparent); if ((frame->mem_dc = CreateMemDCFromMyBitmap (&mybmp, ImageDesc.ColorMap)) == 0) { free (mybmp.bits); free (frame); _MG_PRINTF ("EX_CTRL>GIF89a: Error when expand frame bitmap.\n"); goto error; } frame->bits = mybmp.bits; if (anim->frames == NULL) { anim->frames = frame; current = frame; current->prev = NULL; } else { frame->prev = current; current->next = frame; current = current->next; } anim->nr_frames++ ; } break; } ok = ReadOK (area, &c, 1); } return anim; error: DestroyAnimation (anim, TRUE); return NULL; }
static LRESULT CALLBACK ACCWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ACCData* data = (ACCData *) GetWindowLongPtr(hwnd, 0); switch(msg) { case WM_NCCREATE: { SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) | BS_OWNERDRAW); SetWindowLongPtr(hwnd, GWL_EXSTYLE, GetWindowLongPtr(hwnd, GWL_EXSTYLE) | WS_EX_TRANSPARENT); data = (ACCData*) mir_alloc(sizeof(ACCData)); if (data == NULL) return FALSE; SetWindowLongPtr(hwnd, 0, (LONG_PTR)data); ZeroMemory(data, sizeof(ACCData)); data->hHook = HookEventMessage(ME_AV_AVATARCHANGED, hwnd, DM_AVATARCHANGED); data->hHookMy = HookEventMessage(ME_AV_MYAVATARCHANGED, hwnd, DM_MYAVATARCHANGED); data->hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT); data->borderColor = -1; data->bkgColor = -1; data->avatarBorderColor = -1; data->respectHidden = TRUE; data->showingFlash = FALSE; data->resizeIfSmaller = TRUE; data->showingAnimatedGif = FALSE; data->fAero = FALSE; return TRUE; } case WM_NCDESTROY: { DestroyAnimation(hwnd, data); if (data) { UnhookEvent(data->hHook); UnhookEvent(data->hHookMy); mir_free(data); } SetWindowLongPtr(hwnd, 0, (LONG_PTR)NULL); break; } case WM_SETFONT: { data->hFont = (HFONT)wParam; Invalidate(hwnd); break; } case AVATAR_SETCONTACT: { DestroyAnimation(hwnd, data); data->hContact = lParam; if (lParam == NULL) data->proto[0] = '\0'; else lstrcpynA(data->proto, GetContactProto(data->hContact), sizeof(data->proto)); StartAnimation(hwnd, data); NotifyAvatarChange(hwnd); Invalidate(hwnd); return TRUE; } case AVATAR_SETPROTOCOL: { DestroyAnimation(hwnd, data); data->hContact = NULL; if (lParam == NULL) data->proto[0] = '\0'; else lstrcpynA(data->proto, (char *) lParam, sizeof(data->proto)); StartAnimation(hwnd, data); NotifyAvatarChange(hwnd); Invalidate(hwnd); return TRUE; } case AVATAR_SETBKGCOLOR: { data->bkgColor = (COLORREF) lParam; if (data->showingFlash) SetBkgFlash(hwnd, data); NotifyAvatarChange(hwnd); Invalidate(hwnd); return TRUE; } case AVATAR_SETBORDERCOLOR: { data->borderColor = (COLORREF) lParam; if (data->showingFlash) ResizeFlash(hwnd, data); NotifyAvatarChange(hwnd); Invalidate(hwnd); return TRUE; } case AVATAR_SETAVATARBORDERCOLOR: { data->avatarBorderColor = (COLORREF) lParam; if (data->showingFlash) ResizeFlash(hwnd, data); NotifyAvatarChange(hwnd); Invalidate(hwnd); return TRUE; } case AVATAR_SETAVATARROUNDCORNERRADIUS: { data->avatarRoundCornerRadius = (int) lParam; NotifyAvatarChange(hwnd); Invalidate(hwnd); return TRUE; } case AVATAR_SETNOAVATARTEXT: { lstrcpyn(data->noAvatarText, TranslateTS((TCHAR*) lParam), SIZEOF(data->noAvatarText)); Invalidate(hwnd); return TRUE; } case AVATAR_RESPECTHIDDEN: { data->respectHidden = (BOOL) lParam; NotifyAvatarChange(hwnd); Invalidate(hwnd); return TRUE; } case AVATAR_SETRESIZEIFSMALLER: { data->resizeIfSmaller = (BOOL) lParam; NotifyAvatarChange(hwnd); Invalidate(hwnd); return TRUE; } case AVATAR_SETAEROCOMPATDRAWING: data->fAero = lParam; return(TRUE); case AVATAR_GETUSEDSPACE: { int *width = (int *)wParam; int *height = (int *)lParam; RECT rc; GetClientRect(hwnd, &rc); // Get avatar if (data->showingFlash && ServiceExists(MS_FAVATAR_GETINFO)) { FLASHAVATAR fa = {0}; fa.hContact = data->hContact; fa.cProto = data->proto; fa.hParentWindow = hwnd; fa.id = 1675; CallService(MS_FAVATAR_GETINFO, (WPARAM)&fa, 0); if (fa.hWindow != NULL) { *width = rc.right - rc.left; *height = rc.bottom - rc.top; return TRUE; } } avatarCacheEntry *ace; if (data->hContact == NULL) ace = (avatarCacheEntry *) CallService(MS_AV_GETMYAVATAR, 0, (LPARAM) data->proto); else ace = (avatarCacheEntry *) CallService(MS_AV_GETAVATARBITMAP, (WPARAM) data->hContact, 0); if (ace == NULL || ace->bmHeight == 0 || ace->bmWidth == 0 || (data->respectHidden && (ace->dwFlags & AVS_HIDEONCLIST))) { *width = 0; *height = 0; return TRUE; } // Get its size int targetWidth = rc.right - rc.left; int targetHeight = rc.bottom - rc.top; if (!data->resizeIfSmaller && ace->bmHeight <= targetHeight && ace->bmWidth <= targetWidth) { *height = ace->bmHeight; *width = ace->bmWidth; } else if (ace->bmHeight > ace->bmWidth) { float dScale = targetHeight / (float)ace->bmHeight; *height = targetHeight; *width = (int) (ace->bmWidth * dScale); } else { float dScale = targetWidth / (float)ace->bmWidth; *height = (int) (ace->bmHeight * dScale); *width = targetWidth; } return TRUE; } case DM_AVATARCHANGED: { if (data->hContact == wParam) { DestroyAnimation(hwnd, data); StartAnimation(hwnd, data); NotifyAvatarChange(hwnd); Invalidate(hwnd); } break; } case DM_MYAVATARCHANGED: { if (data->hContact == NULL && strcmp(data->proto, (char*) wParam) == 0) { DestroyAnimation(hwnd, data); StartAnimation(hwnd, data); NotifyAvatarChange(hwnd); Invalidate(hwnd); } break; } case WM_NCPAINT: case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); if (hdc == NULL) break; int oldBkMode = SetBkMode(hdc, TRANSPARENT); SetStretchBltMode(hdc, HALFTONE); RECT rc; GetClientRect(hwnd, &rc); // Draw background if (data->bkgColor != -1) { HBRUSH hbrush = CreateSolidBrush(data->bkgColor); FillRect(hdc, &rc, hbrush); DeleteObject(hbrush); } if (data->hContact == NULL && data->proto[0] == '\0' && db_get_b(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1)) { DrawText(hdc, data->hFont, rc, TranslateT("Protocols have different avatars")); } // Has a flash avatar else if (data->showingFlash) { // Don't draw // Draw control border if needed if (data->borderColor == -1 && data->avatarBorderColor != -1) { HBRUSH hbrush = CreateSolidBrush(data->avatarBorderColor); FrameRect(hdc, &rc, hbrush); DeleteObject(hbrush); } } // Has an animated gif // Has a "normal" image else { // Draw avatar AVATARDRAWREQUEST avdrq = {0}; avdrq.cbSize = sizeof(avdrq); avdrq.rcDraw = rc; avdrq.hContact = data->hContact; avdrq.szProto = data->proto; avdrq.hTargetDC = hdc; avdrq.dwFlags = AVDRQ_HIDEBORDERONTRANSPARENCY | (data->respectHidden ? AVDRQ_RESPECTHIDDEN : 0) | (data->hContact != NULL ? 0 : AVDRQ_OWNPIC) | (data->avatarBorderColor == -1 ? 0 : AVDRQ_DRAWBORDER) | (data->avatarRoundCornerRadius <= 0 ? 0 : AVDRQ_ROUNDEDCORNER) | (data->fAero ? AVDRQ_AERO : 0) | (data->resizeIfSmaller ? 0 : AVDRQ_DONTRESIZEIFSMALLER); avdrq.clrBorder = data->avatarBorderColor; avdrq.radius = data->avatarRoundCornerRadius; INT_PTR ret; if (data->showingAnimatedGif) { InternalDrawAvatar(&avdrq, data->ag.hbms[data->ag.frame.num], data->ag.logicalWidth, data->ag.logicalHeight, 0); ret = 1; if (!data->ag.started) { SetTimer(hwnd, 0, data->ag.times[data->ag.frame.num], NULL); data->ag.started = TRUE; } } else ret = DrawAvatarPicture(0, (LPARAM)&avdrq); if (ret == 0) DrawText(hdc, data->hFont, rc, data->noAvatarText); } // Draw control border if (data->borderColor != -1) { HBRUSH hbrush = CreateSolidBrush(data->borderColor); FrameRect(hdc, &rc, hbrush); DeleteObject(hbrush); } SetBkMode(hdc, oldBkMode); EndPaint(hwnd, &ps); return TRUE; } case WM_ERASEBKGND: { HDC hdc = (HDC) wParam; RECT rc; GetClientRect(hwnd, &rc); // Draw background if (data->bkgColor != -1) { HBRUSH hbrush = CreateSolidBrush(data->bkgColor); FillRect(hdc, &rc, hbrush); DeleteObject(hbrush); } // Draw control border if (data->borderColor != -1) { HBRUSH hbrush = CreateSolidBrush(data->borderColor); FrameRect(hdc, &rc, hbrush); DeleteObject(hbrush); } return TRUE; } case WM_SIZE: { if (data->showingFlash) ResizeFlash(hwnd, data); InvalidateRect(hwnd, NULL, TRUE); break; } case WM_TIMER: { if (wParam != 0) break; KillTimer(hwnd, 0); if (!data->showingAnimatedGif) break; AnimatedGifDispodeFrame(data); int frame = data->ag.frame.num + 1; if (frame >= data->ag.frameCount) { // Don't need fi data no more AnimatedGifDeleteTmpValues(data); frame = 0; } AnimatedGifMountFrame(data, frame); data->ag.started = FALSE; InvalidateRect(hwnd, NULL, FALSE); break; } } return DefWindowProc(hwnd, msg, wParam, lParam); }
void DestroyVisual(Visual *& visual){ DestroyAnimation(visual->animation); SafeDelete(visual->rect); SafeDelete(visual); }