winamp/Src/auth/Loginbox/imageCache.cpp

357 lines
7.6 KiB
C++
Raw Normal View History

2024-09-24 12:54:57 +00:00
#include "./imageCache.h"
#include "./imageLoader.h"
#include "./graphics.h"
#include "./loginBox.h"
#include <api/service/waservicefactory.h>
#include "../../ombrowser/ifc_omutility.h"
#include "../../ombrowser/ifc_omcachemanager.h"
#include "../../ombrowser/ifc_omcachegroup.h"
#include "../../ombrowser/ifc_omcacherecord.h"
#include "../api.h"
LoginImageCache::LoginImageCache(HWND hLoginbox)
: ref(1), hwnd(hLoginbox), group(NULL)
{
InitializeCriticalSection(&lock);
}
LoginImageCache::~LoginImageCache()
{
if (NULL != group)
{
group->Release();
}
DeleteCriticalSection(&lock);
}
HRESULT LoginImageCache::CreateInstance(HWND hLoginbox, LoginImageCache **instance)
{
if (NULL == instance)
return E_POINTER;
*instance = NULL;
if (NULL == hLoginbox) return E_INVALIDARG;
*instance = new LoginImageCache(hLoginbox);
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
size_t LoginImageCache::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t LoginImageCache::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int LoginImageCache::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object) return E_POINTER;
if (IsEqualIID(interface_guid, IFC_OmCacheCallback))
*object = static_cast<ifc_omcachecallback*>(this);
else
{
*object = NULL;
return E_NOINTERFACE;
}
if (NULL == *object)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
void LoginImageCache::PathChanged(ifc_omcacherecord *record)
{
HWND hLoginbox;
EnterCriticalSection(&lock);
hLoginbox = hwnd;
LeaveCriticalSection(&lock);
if (NULL != hLoginbox && FALSE != IsWindow(hLoginbox))
{
IMAGECACHERESULT result;
result.imageCache = this;
result.cacheRecord = record;
SendMessage(hLoginbox, NLBM_IMAGECACHED, 0, (LPARAM)&result);
}
}
void LoginImageCache::Finish()
{
EnterCriticalSection(&lock);
ifc_omcachegroup *groupCopy = group;
if (NULL != groupCopy)
groupCopy->AddRef();
LeaveCriticalSection(&lock);
if (NULL != groupCopy)
{
groupCopy->Clear();
WCHAR szGroup[64] = {0};
if (SUCCEEDED(groupCopy->GetName(szGroup, ARRAYSIZE(szGroup))))
{
waServiceFactory *serviceFactory = WASABI_API_SVC->service_getServiceByGuid(IFC_OmUtility);
if (NULL != serviceFactory)
{
ifc_omutility *omUtility = (ifc_omutility*)serviceFactory->getInterface();
if (NULL != omUtility)
{
ifc_omcachemanager *cacheManager;
if (SUCCEEDED(omUtility->GetCacheManager(&cacheManager)))
{
cacheManager->Delete(szGroup);
cacheManager->Release();
}
omUtility->Release();
}
}
}
groupCopy->Release();
}
}
HRESULT LoginImageCache::InitGroup()
{
HRESULT hr;
EnterCriticalSection(&lock);
if (NULL != group)
{
hr = S_FALSE;
}
else
{
hr = S_OK;
waServiceFactory *serviceFactory = WASABI_API_SVC->service_getServiceByGuid(IFC_OmUtility);
if (NULL != serviceFactory)
{
ifc_omutility *omUtility = (ifc_omutility*)serviceFactory->getInterface();
if (NULL != omUtility)
{
ifc_omcachemanager *cacheManager;
if (SUCCEEDED(omUtility->GetCacheManager(&cacheManager)))
{
if (FAILED(cacheManager->Find(L"loginBox", TRUE, &group, NULL)))
group = NULL;
cacheManager->Release();
}
omUtility->Release();
}
}
if (NULL == group)
hr = E_NOINTERFACE;
}
LeaveCriticalSection(&lock);
return hr;
}
HRESULT LoginImageCache::GetImageListIndex(LPCWSTR pszPath, HIMAGELIST himl, UINT *index, UINT *indexActive, UINT *indexDisabled)
{
if (NULL == pszPath || L'\0' == *pszPath)
return E_INVALIDARG;
HRESULT hr;
WCHAR szBuffer[2048] = {0};
EnterCriticalSection(&lock);
BOOL fCreated = FALSE;
hr = InitGroup();
if (SUCCEEDED(hr))
{
ifc_omcacherecord *record;
hr = group->Find(pszPath, TRUE, &record, &fCreated);
if (S_OK != hr)
{
if (S_FALSE == hr)
hr = E_PENDING;
}
else
{
record->RegisterCallback(this);
hr = record->GetPath(szBuffer, ARRAYSIZE(szBuffer));
record->Release();
}
}
LeaveCriticalSection(&lock);
if (FAILED(hr))
return hr;
return GetImageListIndexLocal(szBuffer, himl, index, indexActive, indexDisabled);
}
HRESULT LoginImageCache::GetImageListIndexLocal(LPCWSTR pszPath, HIMAGELIST himl, UINT *index, UINT *indexActive, UINT *indexDisabled)
{
if (NULL == himl || NULL == pszPath || L'\0' == *pszPath)
return E_INVALIDARG;
if (NULL == index && NULL == indexActive && NULL == indexDisabled)
return E_INVALIDARG;
INT destWidth, destHeight;
if (0 == ImageList_GetIconSize(himl, &destWidth, &destHeight))
return E_FAIL;
INT imageWidth, imageHeight;
HBITMAP hbmp = ImageLoader_LoadBitmap(NULL, pszPath, FALSE, &imageWidth, &imageHeight);
if (NULL == hbmp)
return E_FAIL;
HRESULT hr = S_OK;
RECT imageRect;
SetRect(&imageRect, 0, 0, imageWidth, imageHeight);
if (NULL != indexActive)
{
*indexActive = ImageList_Add(himl, hbmp, NULL);
if (((UINT)-1) == *indexActive) hr = E_FAIL;
}
if (NULL != index)
{
Image_AdjustSaturationAlpha(hbmp, &imageRect, -150, -100);
*index = ImageList_Add(himl, hbmp, NULL);
if (((UINT)-1) == *index) hr = E_FAIL;
}
if (NULL != indexDisabled)
{
Image_AdjustSaturationAlpha(hbmp, &imageRect, -600, -600);
*indexDisabled = ImageList_Add(himl, hbmp, NULL);
if (((UINT)-1) == *indexDisabled) hr = E_FAIL;
}
if (NULL != hbmp)
DeleteObject(hbmp);
return hr;
}
HBITMAP LoginImageCache::AdjustBitmapSize(HBITMAP hBitmap, INT forceWidth, INT forceHeight)
{
BITMAP bm;
if (sizeof(BITMAP) != GetObject(hBitmap, sizeof(bm), &bm))
return NULL;
if (bm.bmHeight < 0) bm.bmHeight = -bm.bmHeight;
if (bm.bmWidth == forceWidth && bm.bmHeight == forceHeight)
return hBitmap;
HDC hdc, hdcSrc, hdcDst;
hdc = GetDCEx(NULL, NULL, DCX_CACHE | DCX_WINDOW | DCX_NORESETATTRS);
if (NULL == hdc) return NULL;
hdcSrc = CreateCompatibleDC(hdc);
hdcDst = CreateCompatibleDC(hdc);
BITMAPINFOHEADER bhi;
ZeroMemory(&bhi, sizeof(bhi));
bhi.biSize = sizeof(bhi);
bhi.biCompression = BI_RGB;
bhi.biBitCount = 32;
bhi.biPlanes = 1;
bhi.biWidth = forceWidth;
bhi.biHeight = -forceHeight;
UINT *pixelData;
HBITMAP hbmpDst = CreateDIBSection(NULL, (LPBITMAPINFO)&bhi, DIB_RGB_COLORS, (void**)&pixelData, NULL, 0);
if (NULL != hbmpDst)
{
for (INT i = 0; i < forceWidth * forceHeight; i++)
pixelData[i] = 0x00FFFFFF;
}
ReleaseDC(NULL, hdc);
if (NULL != hdcSrc && NULL != hdcDst && NULL != hbmpDst)
{
HBITMAP hbmpSrcOrig = (HBITMAP)SelectObject(hdcSrc, hBitmap);
HBITMAP hbmpDstOrig = (HBITMAP)SelectObject(hdcDst, hbmpDst);
BOOL result;
if (bm.bmWidth <= forceWidth && bm.bmHeight <= forceHeight)
{
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 255;
bf.AlphaFormat = AC_SRC_ALPHA;
result = GdiAlphaBlend(hdcDst, (forceWidth - bm.bmWidth)/2, (forceHeight - bm.bmHeight)/2,
bm.bmWidth, bm.bmHeight, hdcSrc, 0, 0, bm.bmWidth, bm.bmHeight, bf);
}
else
{
SetStretchBltMode(hdcDst, HALFTONE);
result = StretchBlt(hdcDst, 0, 0, forceWidth, forceHeight,
hdcSrc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
}
if(FALSE != result)
{
hBitmap = hbmpDst;
hbmpDst = NULL;
}
else
hBitmap = NULL;
SelectObject(hdcSrc, hbmpSrcOrig);
SelectObject(hdcDst, hbmpDstOrig);
}
else
{
hBitmap = NULL;
}
if (NULL != hdcDst) DeleteDC(hdcDst);
if (NULL != hdcSrc) DeleteDC(hdcSrc);
if (NULL != hbmpDst) DeleteObject(hbmpDst);
return hBitmap;
}
#define CBCLASS LoginImageCache
START_DISPATCH;
CB(ADDREF, AddRef)
CB(RELEASE, Release)
CB(QUERYINTERFACE, QueryInterface)
VCB(API_PATHCHANGED, PathChanged)
END_DISPATCH;
#undef CBCLASS