[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.
This commit is contained in:
Ethan Rodensky 2023-08-06 18:14:51 -04:00 committed by Stanislav Motylkov
parent a0250607f2
commit e31031f603
4 changed files with 131 additions and 1 deletions

View file

@ -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)

View file

@ -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);

View file

@ -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@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;
}

View file

@ -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);