mirror of
https://github.com/reactos/reactos.git
synced 2024-08-26 05:08:39 +00:00
157 lines
3.9 KiB
C
157 lines
3.9 KiB
C
/*
|
|
* PROJECT: ReactOS Picture and Fax Viewer
|
|
* LICENSE: GPL-2.0 (https://spdx.org/licenses/GPL-2.0)
|
|
* PURPOSE: Animation of shimgvw.dll
|
|
* COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
|
*/
|
|
|
|
#include "shimgvw.h"
|
|
|
|
#define ANIME_TIMER_ID 9999
|
|
|
|
void Anime_FreeInfo(PANIME pAnime)
|
|
{
|
|
if (pAnime->m_pDelayItem)
|
|
{
|
|
QuickFree(pAnime->m_pDelayItem);
|
|
pAnime->m_pDelayItem = NULL;
|
|
}
|
|
pAnime->m_nFrameIndex = 0;
|
|
pAnime->m_nFrameCount = 0;
|
|
pAnime->m_nLoopIndex = 0;
|
|
pAnime->m_nLoopCount = (UINT)-1;
|
|
}
|
|
|
|
void Anime_SetTimerWnd(PANIME pAnime, HWND hwndTimer)
|
|
{
|
|
pAnime->m_hwndTimer = hwndTimer;
|
|
}
|
|
|
|
void Anime_Pause(PANIME pAnime)
|
|
{
|
|
KillTimer(pAnime->m_hwndTimer, ANIME_TIMER_ID);
|
|
}
|
|
|
|
void Anime_Start(PANIME pAnime, DWORD dwDelay)
|
|
{
|
|
if (pAnime->m_pDelayItem)
|
|
SetTimer(pAnime->m_hwndTimer, ANIME_TIMER_ID, dwDelay, NULL);
|
|
}
|
|
|
|
DWORD Anime_GetFrameDelay(PANIME pAnime, UINT nFrameIndex)
|
|
{
|
|
if (nFrameIndex < pAnime->m_nFrameCount && pAnime->m_pDelayItem)
|
|
{
|
|
return ((DWORD *)pAnime->m_pDelayItem->value)[pAnime->m_nFrameIndex] * 10;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
BOOL Anime_Step(PANIME pAnime, DWORD *pdwDelay)
|
|
{
|
|
*pdwDelay = INFINITE;
|
|
if (pAnime->m_nLoopCount == (UINT)-1)
|
|
return FALSE;
|
|
|
|
if (pAnime->m_nFrameIndex + 1 < pAnime->m_nFrameCount)
|
|
{
|
|
*pdwDelay = Anime_GetFrameDelay(pAnime, pAnime->m_nFrameIndex);
|
|
Anime_SetFrameIndex(pAnime, pAnime->m_nFrameIndex);
|
|
++pAnime->m_nFrameIndex;
|
|
return TRUE;
|
|
}
|
|
|
|
if (pAnime->m_nLoopCount == 0 || pAnime->m_nLoopIndex < pAnime->m_nLoopCount)
|
|
{
|
|
*pdwDelay = Anime_GetFrameDelay(pAnime, pAnime->m_nFrameIndex);
|
|
Anime_SetFrameIndex(pAnime, pAnime->m_nFrameIndex);
|
|
pAnime->m_nFrameIndex = 0;
|
|
++pAnime->m_nLoopIndex;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL Anime_OnTimer(PANIME pAnime, WPARAM wParam)
|
|
{
|
|
DWORD dwDelay;
|
|
|
|
if (wParam != ANIME_TIMER_ID)
|
|
return FALSE;
|
|
|
|
Anime_Pause(pAnime);
|
|
if (Anime_Step(pAnime, &dwDelay))
|
|
Anime_Start(pAnime, dwDelay);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL Anime_LoadInfo(PANIME pAnime)
|
|
{
|
|
UINT nDimCount = 0;
|
|
UINT cbItem;
|
|
UINT result;
|
|
|
|
Anime_Pause(pAnime);
|
|
Anime_FreeInfo(pAnime);
|
|
|
|
if (!g_pImage)
|
|
return FALSE;
|
|
|
|
GdipImageGetFrameDimensionsCount(g_pImage, &nDimCount);
|
|
if (nDimCount)
|
|
{
|
|
GUID *dims = (GUID *)QuickAlloc(nDimCount * sizeof(GUID), TRUE);
|
|
if (dims)
|
|
{
|
|
GdipImageGetFrameDimensionsList(g_pImage, dims, nDimCount);
|
|
GdipImageGetFrameCount(g_pImage, dims, &result);
|
|
pAnime->m_nFrameCount = result;
|
|
QuickFree(dims);
|
|
}
|
|
}
|
|
|
|
result = 0;
|
|
GdipGetPropertyItemSize(g_pImage, PropertyTagFrameDelay, &result);
|
|
cbItem = result;
|
|
if (cbItem)
|
|
{
|
|
pAnime->m_pDelayItem = (PropertyItem *)QuickAlloc(cbItem, FALSE);
|
|
GdipGetPropertyItem(g_pImage, PropertyTagFrameDelay, cbItem, pAnime->m_pDelayItem);
|
|
}
|
|
|
|
result = 0;
|
|
GdipGetPropertyItemSize(g_pImage, PropertyTagLoopCount, &result);
|
|
cbItem = result;
|
|
if (cbItem)
|
|
{
|
|
PropertyItem *pItem = (PropertyItem *)QuickAlloc(cbItem, FALSE);
|
|
if (pItem)
|
|
{
|
|
if (GdipGetPropertyItem(g_pImage, PropertyTagLoopCount, cbItem, pItem) == Ok)
|
|
{
|
|
pAnime->m_nLoopCount = *(WORD *)pItem->value;
|
|
}
|
|
QuickFree(pItem);
|
|
}
|
|
}
|
|
|
|
Anime_Start(pAnime, 0);
|
|
|
|
return pAnime->m_pDelayItem != NULL;
|
|
}
|
|
|
|
void Anime_SetFrameIndex(PANIME pAnime, UINT nFrameIndex)
|
|
{
|
|
if (nFrameIndex < pAnime->m_nFrameCount)
|
|
{
|
|
GUID guid = FrameDimensionTime;
|
|
if (Ok != GdipImageSelectActiveFrame(g_pImage, &guid, nFrameIndex))
|
|
{
|
|
guid = FrameDimensionPage;
|
|
GdipImageSelectActiveFrame(g_pImage, &guid, nFrameIndex);
|
|
}
|
|
}
|
|
pAnime->m_nFrameIndex = nFrameIndex;
|
|
}
|