https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0fe0b40ee18be504821f29624987b7df154cb49d

commit 0fe0b40ee18be504821f29624987b7df154cb49d
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Sun Dec 10 14:07:46 2023 +0900
Commit:     GitHub <nore...@github.com>
CommitDate: Sun Dec 10 14:07:46 2023 +0900

    [SHIMGVW] Split animation code to anime.c (#6144)
    
    Improve code flexibility.
    Add anime.c and move animation code to anime.c.
    CORE-19358
---
 dll/win32/shimgvw/CMakeLists.txt |   1 +
 dll/win32/shimgvw/anime.c        | 156 +++++++++++++++++++++++++++++
 dll/win32/shimgvw/shimgvw.c      | 210 ++++-----------------------------------
 dll/win32/shimgvw/shimgvw.h      |  59 ++++++++++-
 4 files changed, 231 insertions(+), 195 deletions(-)

diff --git a/dll/win32/shimgvw/CMakeLists.txt b/dll/win32/shimgvw/CMakeLists.txt
index 11df2db4098..3c2f5a1f3c3 100644
--- a/dll/win32/shimgvw/CMakeLists.txt
+++ b/dll/win32/shimgvw/CMakeLists.txt
@@ -2,6 +2,7 @@
 spec2def(shimgvw.dll shimgvw.spec)
 
 list(APPEND SOURCE
+    anime.c
     shimgvw.c
     comsup.c
     shimgvw.rc
diff --git a/dll/win32/shimgvw/anime.c b/dll/win32/shimgvw/anime.c
new file mode 100644
index 00000000000..485b509675b
--- /dev/null
+++ b/dll/win32/shimgvw/anime.c
@@ -0,0 +1,156 @@
+/*
+ * 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...@gmail.com)
+ */
+
+#include "shimgvw.h"
+
+#define ANIME_TIMER_ID  9999
+
+void Anime_FreeInfo(PANIME pAnime)
+{
+    if (pAnime->m_pDelayItem)
+    {
+        free(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);
+}
+
+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 *)calloc(nDimCount, sizeof(GUID));
+        if (dims)
+        {
+            GdipImageGetFrameDimensionsList(g_pImage, dims, nDimCount);
+            GdipImageGetFrameCount(g_pImage, dims, &result);
+            pAnime->m_nFrameCount = result;
+            free(dims);
+        }
+    }
+
+    result = 0;
+    GdipGetPropertyItemSize(g_pImage, PropertyTagFrameDelay, &result);
+    cbItem = result;
+    if (cbItem)
+    {
+        pAnime->m_pDelayItem = (PropertyItem *)malloc(cbItem);
+        GdipGetPropertyItem(g_pImage, PropertyTagFrameDelay, cbItem, 
pAnime->m_pDelayItem);
+    }
+
+    result = 0;
+    GdipGetPropertyItemSize(g_pImage, PropertyTagLoopCount, &result);
+    cbItem = result;
+    if (cbItem)
+    {
+        PropertyItem *pItem = (PropertyItem *)malloc(cbItem);
+        if (pItem)
+        {
+            if (GdipGetPropertyItem(g_pImage, PropertyTagLoopCount, cbItem, 
pItem) == Ok)
+            {
+                pAnime->m_nLoopCount = *(WORD *)pItem->value;
+            }
+            free(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;
+}
+
+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;
+}
diff --git a/dll/win32/shimgvw/shimgvw.c b/dll/win32/shimgvw/shimgvw.c
index 7a73eeaccb3..f8915000893 100644
--- a/dll/win32/shimgvw/shimgvw.c
+++ b/dll/win32/shimgvw/shimgvw.c
@@ -1,37 +1,19 @@
 /*
- * PROJECT:         ReactOS Picture and Fax Viewer
- * FILE:            dll/win32/shimgvw/shimgvw.c
- * PURPOSE:         shimgvw.dll
- * PROGRAMMERS:     Dmitry Chapyshev (dmi...@reactos.org)
- *                  Katayama Hirofumi MZ (katayama.hirofumi...@gmail.com)
+ * PROJECT:     ReactOS Picture and Fax Viewer
+ * LICENSE:     GPL-2.0 (https://spdx.org/licenses/GPL-2.0)
+ * PURPOSE:     Image file browsing and manipulation
+ * COPYRIGHT:   Copyright Dmitry Chapyshev (dmi...@reactos.org)
+ *              Copyright 2018-2023 Katayama Hirofumi MZ 
(katayama.hirofumi...@gmail.com)
  */
 
-#define WIN32_NO_STATUS
-#define _INC_WINDOWS
-#define COM_NO_WINDOWS_H
-#define INITGUID
-
-#include <windef.h>
-#include <winbase.h>
-#include <winnls.h>
-#include <winreg.h>
-#include <wingdi.h>
-#include <wincon.h>
+#include "shimgvw.h"
 #include <windowsx.h>
-#include <objbase.h>
 #include <commctrl.h>
 #include <commdlg.h>
-#include <gdiplus.h>
 #include <shlobj.h>
-#include <strsafe.h>
 #include <shlwapi.h>
 #include <shellapi.h>
 
-#define NDEBUG
-#include <debug.h>
-
-#include "shimgvw.h"
-
 HINSTANCE g_hInstance;
 SHIMGVW_SETTINGS g_Settings;
 SHIMGVW_FILENODE *g_pCurrentFile;
@@ -41,6 +23,8 @@ WNDPROC g_fnPrevProc = NULL;
 HWND g_hDispWnd = NULL;
 HWND g_hToolBar = NULL;
 
+ANIME g_Anime; /* Animation */
+
 /* zooming */
 static UINT s_nZoomPercents = 100;
 
@@ -109,135 +93,6 @@ static const TB_BUTTON_CONFIG s_ButtonConfig[] =
     DEFINE_BTN_CONFIG(HELP_TOC)
 };
 
-/* animation */
-UINT            m_nFrameIndex = 0;
-UINT            m_nFrameCount = 0;
-UINT            m_nLoopIndex = 0;
-UINT            m_nLoopCount = (UINT)-1;
-PropertyItem   *m_pDelayItem = NULL;
-
-#define ANIME_TIMER_ID  9999
-
-static void Anime_FreeInfo(void)
-{
-    if (m_pDelayItem)
-    {
-        free(m_pDelayItem);
-        m_pDelayItem = NULL;
-    }
-    m_nFrameIndex = 0;
-    m_nFrameCount = 0;
-    m_nLoopIndex = 0;
-    m_nLoopCount = (UINT)-1;
-}
-
-static BOOL Anime_LoadInfo(void)
-{
-    UINT nDimCount = 0;
-    UINT cbItem;
-    UINT result;
-
-    Anime_FreeInfo();
-    KillTimer(g_hDispWnd, ANIME_TIMER_ID);
-
-    if (!g_pImage)
-        return FALSE;
-
-    GdipImageGetFrameDimensionsCount(g_pImage, &nDimCount);
-    if (nDimCount)
-    {
-        GUID *dims = (GUID *)calloc(nDimCount, sizeof(GUID));
-        if (dims)
-        {
-            GdipImageGetFrameDimensionsList(g_pImage, dims, nDimCount);
-            GdipImageGetFrameCount(g_pImage, dims, &result);
-            m_nFrameCount = result;
-            free(dims);
-        }
-    }
-
-    result = 0;
-    GdipGetPropertyItemSize(g_pImage, PropertyTagFrameDelay, &result);
-    cbItem = result;
-    if (cbItem)
-    {
-        m_pDelayItem = (PropertyItem *)malloc(cbItem);
-        GdipGetPropertyItem(g_pImage, PropertyTagFrameDelay, cbItem, 
m_pDelayItem);
-    }
-
-    result = 0;
-    GdipGetPropertyItemSize(g_pImage, PropertyTagLoopCount, &result);
-    cbItem = result;
-    if (cbItem)
-    {
-        PropertyItem *pItem = (PropertyItem *)malloc(cbItem);
-        if (pItem)
-        {
-            if (GdipGetPropertyItem(g_pImage, PropertyTagLoopCount, cbItem, 
pItem) == Ok)
-            {
-                m_nLoopCount = *(WORD *)pItem->value;
-            }
-            free(pItem);
-        }
-    }
-
-    if (m_pDelayItem)
-    {
-        SetTimer(g_hDispWnd, ANIME_TIMER_ID, 0, NULL);
-    }
-
-    return m_pDelayItem != NULL;
-}
-
-static void Anime_SetFrameIndex(UINT nFrameIndex)
-{
-    if (nFrameIndex < m_nFrameCount)
-    {
-        GUID guid = FrameDimensionTime;
-        if (Ok != GdipImageSelectActiveFrame(g_pImage, &guid, nFrameIndex))
-        {
-            guid = FrameDimensionPage;
-            GdipImageSelectActiveFrame(g_pImage, &guid, nFrameIndex);
-        }
-    }
-    m_nFrameIndex = nFrameIndex;
-}
-
-DWORD Anime_GetFrameDelay(UINT nFrameIndex)
-{
-    if (nFrameIndex < m_nFrameCount && m_pDelayItem)
-    {
-        return ((DWORD *)m_pDelayItem->value)[m_nFrameIndex] * 10;
-    }
-    return 0;
-}
-
-BOOL Anime_Step(DWORD *pdwDelay)
-{
-    *pdwDelay = INFINITE;
-    if (m_nLoopCount == (UINT)-1)
-        return FALSE;
-
-    if (m_nFrameIndex + 1 < m_nFrameCount)
-    {
-        *pdwDelay = Anime_GetFrameDelay(m_nFrameIndex);
-        Anime_SetFrameIndex(m_nFrameIndex);
-        ++m_nFrameIndex;
-        return TRUE;
-    }
-
-    if (m_nLoopCount == 0 || m_nLoopIndex < m_nLoopCount)
-    {
-        *pdwDelay = Anime_GetFrameDelay(m_nFrameIndex);
-        Anime_SetFrameIndex(m_nFrameIndex);
-        m_nFrameIndex = 0;
-        ++m_nLoopIndex;
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
 static void UpdateZoom(UINT NewZoom, BOOL bEnableBestFit, BOOL bEnableRealSize)
 {
     BOOL bEnableZoomIn, bEnableZoomOut;
@@ -356,7 +211,8 @@ static void pLoadImage(LPCWSTR szOpenFileName)
         DPRINT1("GdipLoadImageFromFile() failed\n");
         return;
     }
-    Anime_LoadInfo();
+
+    Anime_LoadInfo(&g_Anime);
 
     if (szOpenFileName && szOpenFileName[0])
         SHAddToRecentDocs(SHARD_PATHW, szOpenFileName);
@@ -447,27 +303,14 @@ static void pSaveImageAs(HWND hwnd)
 
     if (GetSaveFileNameW(&sfn))
     {
-        if (m_pDelayItem)
-        {
-            /* save animation */
-            KillTimer(g_hDispWnd, ANIME_TIMER_ID);
-
-            DPRINT1("FIXME: save animation\n");
-            if (GdipSaveImageToFile(g_pImage, szSaveFileName, 
&codecInfo[sfn.nFilterIndex - 1].Clsid, NULL) != Ok)
-            {
-                DPRINT1("GdipSaveImageToFile() failed\n");
-            }
+        Anime_Pause(&g_Anime);
 
-            SetTimer(g_hDispWnd, ANIME_TIMER_ID, 0, NULL);
-        }
-        else
+        if (GdipSaveImageToFile(g_pImage, szSaveFileName, 
&codecInfo[sfn.nFilterIndex - 1].Clsid, NULL) != Ok)
         {
-            /* save non-animation */
-            if (GdipSaveImageToFile(g_pImage, szSaveFileName, 
&codecInfo[sfn.nFilterIndex - 1].Clsid, NULL) != Ok)
-            {
-                DPRINT1("GdipSaveImageToFile() failed\n");
-            }
+            DPRINT1("GdipSaveImageToFile() failed\n");
         }
+
+        Anime_Start(&g_Anime, 0);
     }
 
     free(szFilterMask);
@@ -894,19 +737,6 @@ ImageView_CreateToolBar(HWND hwnd)
     return FALSE;
 }
 
-static void ImageView_OnTimer(HWND hwnd)
-{
-    DWORD dwDelay;
-
-    KillTimer(hwnd, ANIME_TIMER_ID);
-    InvalidateRect(hwnd, NULL, FALSE);
-
-    if (Anime_Step(&dwDelay))
-    {
-        SetTimer(hwnd, ANIME_TIMER_ID, dwDelay, NULL);
-    }
-}
-
 LRESULT CALLBACK
 ImageView_DispWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
@@ -919,11 +749,8 @@ ImageView_DispWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, 
LPARAM lParam)
         }
         case WM_TIMER:
         {
-            if (wParam == ANIME_TIMER_ID)
-            {
-                ImageView_OnTimer(hwnd);
-                return 0;
-            }
+            if (Anime_OnTimer(&g_Anime, wParam))
+                InvalidateRect(hwnd, NULL, FALSE);
             break;
         }
     }
@@ -941,6 +768,7 @@ ImageView_InitControls(HWND hwnd)
     g_fnPrevProc = (WNDPROC) SetWindowLongPtr(g_hDispWnd, GWLP_WNDPROC, 
(LPARAM) ImageView_DispWndProc);
 
     ImageView_CreateToolBar(hwnd);
+    Anime_SetTimerWnd(&g_Anime, g_hDispWnd);
 }
 
 static VOID
@@ -1244,7 +1072,7 @@ ImageView_CreateWindow(HWND hwnd, LPCWSTR szFileName)
         g_pImage = NULL;
     }
 
-    Anime_FreeInfo();
+    Anime_FreeInfo(&g_Anime);
 
     GdiplusShutdown(gdiplusToken);
 
diff --git a/dll/win32/shimgvw/shimgvw.h b/dll/win32/shimgvw/shimgvw.h
index 76aa255856f..f66118acd7c 100644
--- a/dll/win32/shimgvw/shimgvw.h
+++ b/dll/win32/shimgvw/shimgvw.h
@@ -1,9 +1,39 @@
+/*
+ * PROJECT:     ReactOS Picture and Fax Viewer
+ * LICENSE:     GPL-2.0 (https://spdx.org/licenses/GPL-2.0)
+ * PURPOSE:     Image file browsing and manipulation
+ * COPYRIGHT:   Copyright Dmitry Chapyshev (dmi...@reactos.org)
+ *              Copyright 2018-2023 Katayama Hirofumi MZ 
(katayama.hirofumi...@gmail.com)
+ */
+
+#pragma once
+
+#define WIN32_NO_STATUS
+#define _INC_WINDOWS
+#define COM_NO_WINDOWS_H
+#define INITGUID
+
+#include <windef.h>
+#include <winbase.h>
+#include <winnls.h>
+#include <winreg.h>
+#include <wingdi.h>
+#include <wincon.h>
+#include <objbase.h>
+#include <gdiplus.h>
+#include <strsafe.h>
+
+#define NDEBUG
+#include <debug.h>
+
 #include "resource.h"
 
 #define TB_IMAGE_WIDTH  16
 #define TB_IMAGE_HEIGHT 16
 
-extern HINSTANCE hInstance;
+extern HINSTANCE g_hInstance;
+extern HWND g_hDispWnd;
+extern GpImage *g_pImage;
 
 typedef struct
 {
@@ -14,11 +44,32 @@ typedef struct
     INT Height;
 } SHIMGVW_SETTINGS;
 
-typedef struct SHIMGVW_FILENODE_INTERNAL
+typedef struct tagSHIMGVW_FILENODE
 {
     WCHAR FileName[MAX_PATH];
-    struct SHIMGVW_FILENODE_INTERNAL *Prev;
-    struct SHIMGVW_FILENODE_INTERNAL *Next;
+    struct tagSHIMGVW_FILENODE *Prev;
+    struct tagSHIMGVW_FILENODE *Next;
 } SHIMGVW_FILENODE;
 
 #define WC_SHIMGVW L"ShImgVw:CPreviewWnd"
+
+/* Animation */
+typedef struct tagANIME
+{
+    UINT           m_nFrameIndex;
+    UINT           m_nFrameCount;
+    UINT           m_nLoopIndex;
+    UINT           m_nLoopCount;
+    PropertyItem  *m_pDelayItem;
+    HWND           m_hwndTimer;
+} ANIME, *PANIME;
+
+void Anime_FreeInfo(PANIME pAnime);
+BOOL Anime_LoadInfo(PANIME pAnime);
+void Anime_SetTimerWnd(PANIME pAnime, HWND hwndTimer);
+void Anime_SetFrameIndex(PANIME pAnime, UINT nFrameIndex);
+DWORD Anime_GetFrameDelay(PANIME pAnime, UINT nFrameIndex);
+void Anime_Start(PANIME pAnime, DWORD dwDelay);
+void Anime_Pause(PANIME pAnime);
+BOOL Anime_Step(PANIME pAnime, DWORD *pdwDelay);
+BOOL Anime_OnTimer(PANIME pAnime, WPARAM wParam);

Reply via email to