https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e31031f603f54cf1751f0…
commit e31031f603f54cf1751f0501d9aaab1e50b02c01
Author: Ethan Rodensky <splitwirez(a)gmail.com>
AuthorDate: Sun Aug 6 18:14:51 2023 -0400
Commit: Stanislav Motylkov <x86corez(a)gmail.com>
CommitDate: Thu Aug 31 20:42:03 2023 +0300
[UXTHEME] Allow PNG images in visual styles (#5540)
This is prerequisite to supporting Vista+ iteration of the msstyles format,
and also for implementing GetThemeStream() later.
Visual styles compiled for Vista+ can now use PNG images in the IMAGE group.
This does not affect the ability to use BMP images, they can be mixed now.
---
dll/win32/uxtheme/CMakeLists.txt | 13 +++++-
dll/win32/uxtheme/msstyles.c | 11 +++++
dll/win32/uxtheme/pngsup.cpp | 94 ++++++++++++++++++++++++++++++++++++++++
dll/win32/uxtheme/uxthemep.h | 14 ++++++
4 files changed, 131 insertions(+), 1 deletion(-)
diff --git a/dll/win32/uxtheme/CMakeLists.txt b/dll/win32/uxtheme/CMakeLists.txt
index 37fefc5b7fa..3124014046b 100644
--- a/dll/win32/uxtheme/CMakeLists.txt
+++ b/dll/win32/uxtheme/CMakeLists.txt
@@ -19,6 +19,13 @@ list(APPEND SOURCE
uxthemep.h
${CMAKE_CURRENT_BINARY_DIR}/uxtheme_stubs.c)
+if(DLL_EXPORT_VERSION GREATER_EQUAL 0x600)
+ add_definitions(-DENABLE_PNG_SUPPORT)
+
+ list(APPEND SOURCE
+ pngsup.cpp)
+endif()
+
add_library(uxtheme MODULE
${SOURCE}
version.rc
@@ -27,6 +34,10 @@ add_library(uxtheme MODULE
set_module_type(uxtheme win32dll)
target_link_libraries(uxtheme wine)
add_delay_importlibs(uxtheme msimg32)
-add_importlibs(uxtheme user32 advapi32 gdi32 msvcrt kernel32 ntdll)
+if(DLL_EXPORT_VERSION GREATER_EQUAL 0x600)
+ add_importlibs(uxtheme user32 advapi32 gdiplus gdi32 shlwapi msvcrt kernel32 ntdll)
+else()
+ add_importlibs(uxtheme user32 advapi32 gdi32 msvcrt kernel32 ntdll)
+endif()
add_pch(uxtheme uxthemep.h SOURCE)
add_cd_file(TARGET uxtheme DESTINATION reactos/system32 FOR all)
diff --git a/dll/win32/uxtheme/msstyles.c b/dll/win32/uxtheme/msstyles.c
index 866d96effd0..1507d3dd405 100644
--- a/dll/win32/uxtheme/msstyles.c
+++ b/dll/win32/uxtheme/msstyles.c
@@ -920,8 +920,19 @@ HBITMAP MSSTYLES_LoadBitmap (PTHEME_CLASS tc, LPCWSTR lpFilename,
BOOL* hasAlpha
}
/* Not found? Load from resources */
img = HeapAlloc (GetProcessHeap(), 0, sizeof (THEME_IMAGE));
+#ifdef ENABLE_PNG_SUPPORT
+ if (MSSTYLES_TryLoadPng(tc->hTheme, szFile, TEXT(L"IMAGE"),
&img->image)) // ...as PNG...
+ {
+ prepare_png_alpha(img->image, hasAlpha);
+ }
+ else // ...or, failing that, as BMP
+ {
+#endif /* ENABLE_PNG_SUPPORT */
img->image = LoadImageW(tc->hTheme, szFile, IMAGE_BITMAP, 0, 0,
LR_CREATEDIBSECTION);
prepare_alpha (img->image, hasAlpha);
+#ifdef ENABLE_PNG_SUPPORT
+ }
+#endif /* ENABLE_PNG_SUPPORT */
img->hasAlpha = *hasAlpha;
/* ...and stow away for later reuse. */
lstrcpyW (img->name, szFile);
diff --git a/dll/win32/uxtheme/pngsup.cpp b/dll/win32/uxtheme/pngsup.cpp
new file mode 100644
index 00000000000..25f53abdae7
--- /dev/null
+++ b/dll/win32/uxtheme/pngsup.cpp
@@ -0,0 +1,94 @@
+/*
+ * PROJECT: ReactOS uxtheme.dll
+ * LICENSE: LGPL-2.1-or-later (
https://spdx.org/licenses/LGPL-2.1-or-later)
+ * PURPOSE: Support for PNG images in visual styles
+ * COPYRIGHT: Copyright 2023 Ethan Rodensky <splitwirez(a)gmail.com>
+ */
+
+#include "uxthemep.h"
+
+#include <ole2.h>
+#include <objidl.h>
+#include <gdiplus.h>
+#include <gdipluscolor.h>
+#include <winreg.h>
+#include <shlwapi.h>
+
+BOOL
+MSSTYLES_TryLoadPng(
+ _In_ HINSTANCE hTheme,
+ _In_ LPCWSTR szFile,
+ _In_ LPCWSTR type,
+ _Out_ HBITMAP *phBitmap)
+{
+ BOOL ret = FALSE;
+
+ HRSRC hRes = FindResourceW(hTheme, szFile, type);
+ if (!hRes)
+ return FALSE;
+
+ HGLOBAL hAlloc = LoadResource(hTheme, hRes);
+ if (!hAlloc)
+ return FALSE;
+
+ DWORD dwSize = SizeofResource(hTheme, hRes);
+ LPVOID pData = LockResource(hAlloc);
+ if ((!pData) || (dwSize <= 0))
+ {
+ FreeResource(hAlloc);
+ return FALSE;
+ }
+
+ IStream* stream = SHCreateMemStream((BYTE*)pData, dwSize);
+ if (stream)
+ {
+ Gdiplus::Bitmap* gdipBitmap = Gdiplus::Bitmap::FromStream(stream, FALSE);
+ stream->Release();
+ if (gdipBitmap)
+ {
+ ret = gdipBitmap->GetHBITMAP(Gdiplus::Color(0, 0, 0, 0), phBitmap) ==
Gdiplus::Ok;
+ delete gdipBitmap;
+ }
+ }
+
+ UnlockResource(pData);
+ FreeResource(hAlloc);
+ return ret;
+}
+
+BOOL
+prepare_png_alpha(
+ _In_ HBITMAP png,
+ _Out_ BOOL* hasAlpha)
+{
+ DIBSECTION dib;
+ int n;
+ BYTE* p;
+
+ *hasAlpha = FALSE;
+
+ if (!png || GetObjectW( png, sizeof(dib), &dib ) != sizeof(dib))
+ return FALSE;
+
+ if (dib.dsBm.bmBitsPixel != 32)
+ /* nothing to do */
+ return TRUE;
+
+ p = (BYTE*)dib.dsBm.bmBits;
+ n = dib.dsBmih.biHeight * dib.dsBmih.biWidth;
+ while (n-- > 0)
+ {
+ int a = p[3] + 1;
+ if (a < 256)
+ {
+ p[0] = MulDiv(p[0], 256, a);
+ p[1] = MulDiv(p[1], 256, a);
+ p[2] = MulDiv(p[2], 256, a);
+
+ *hasAlpha = TRUE;
+ }
+ p += 4;
+ }
+
+ return TRUE;
+}
diff --git a/dll/win32/uxtheme/uxthemep.h b/dll/win32/uxtheme/uxthemep.h
index b721510ca32..af1ffd31a3d 100644
--- a/dll/win32/uxtheme/uxthemep.h
+++ b/dll/win32/uxtheme/uxthemep.h
@@ -115,6 +115,20 @@ PUXINI_FILE MSSTYLES_GetThemeIni(PTHEME_FILE tf);
PTHEME_PARTSTATE MSSTYLES_FindPartState(PTHEME_CLASS tc, int iPartId, int iStateId,
PTHEME_CLASS *tcNext);
PTHEME_PROPERTY MSSTYLES_FindProperty(PTHEME_CLASS tc, int iPartId, int iStateId, int
iPropertyPrimitive, int iPropertyId);
PTHEME_PROPERTY MSSTYLES_FindMetric(PTHEME_FILE tf, int iPropertyPrimitive, int
iPropertyId);
+#ifdef ENABLE_PNG_SUPPORT
+EXTERN_C
+BOOL
+MSSTYLES_TryLoadPng(
+ _In_ HINSTANCE hTheme,
+ _In_ LPCWSTR szFile,
+ _In_ LPCWSTR type,
+ _Out_ HBITMAP *phBitmap);
+EXTERN_C
+BOOL
+prepare_png_alpha(
+ _In_ HBITMAP png,
+ _Out_ BOOL* hasAlpha);
+#endif /* ENABLE_PNG_SUPPORT */
HBITMAP MSSTYLES_LoadBitmap(PTHEME_CLASS tc, LPCWSTR lpFilename, BOOL* hasAlpha);
HRESULT MSSTYLES_GetPropertyBool(PTHEME_PROPERTY tp, BOOL *pfVal);