123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- #include "main.h"
- #include "./pngLoader.h"
- #include "./browserObject.h"
- #include "./ifc_wasabihelper.h"
- #include <shlwapi.h>
- #include <strsafe.h>
- #ifndef LOAD_LIBRARY_AS_IMAGE_RESOURCE
- #define LOAD_LIBRARY_AS_IMAGE_RESOURCE 0x000000020
- #endif //LOAD_LIBRARY_AS_IMAGE_RESOURCE
- PngLoader::PngLoader(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply)
- : ref(1), instance(hInstance), name(NULL), flags(0)
- {
- name = Plugin_DuplicateResString(pszName);
- if (FALSE != fPremultiply)
- flags |= flagPremultiply;
- }
- PngLoader::~PngLoader()
- {
- Plugin_FreeResString(name);
- }
- HRESULT PngLoader::CreateInstance(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply, ifc_omimageloader **imageLoader)
- {
- if (NULL == imageLoader) return E_POINTER;
- *imageLoader = NULL;
- if (NULL == pszName) return E_INVALIDARG;
- *imageLoader = new PngLoader(hInstance, pszName, fPremultiply);
- if (NULL == *imageLoader) return E_OUTOFMEMORY;
-
- return S_OK;
- }
- size_t PngLoader::AddRef()
- {
- return InterlockedIncrement((LONG*)&ref);
- }
- size_t PngLoader::Release()
- {
- if (0 == ref)
- return ref;
-
- LONG r = InterlockedDecrement((LONG*)&ref);
- if (0 == r)
- delete(this);
-
- return r;
- }
- int PngLoader::QueryInterface(GUID interface_guid, void **object)
- {
- return E_NOINTERFACE;
- }
- static HRESULT PngLoader_LoadResourceData(const void *data, unsigned int size, void **dataOut, int *cx, int *cy, BOOL fPremultiply)
- {
- if (NULL == data) return E_INVALIDARG;
- svc_imageLoader *loader = NULL;
- ifc_wasabihelper *wasabi = NULL;
- if (FAILED(Plugin_GetWasabiHelper(&wasabi))) return E_UNEXPECTED;
- HRESULT hr = wasabi->GetPngLoader(&loader);
- wasabi->Release();
- if (FAILED(hr)) return hr;
- *dataOut = (FALSE == fPremultiply) ?
- loader->loadImageData(data, size, cx, cy) :
- loader->loadImage(data, size, cx, cy);
-
- if (NULL == *dataOut)
- hr = E_OUTOFMEMORY;
-
- loader->Release();
- return hr;
- }
- static HRESULT PngLoader_LoadFromResource(HINSTANCE hInstance, LPCWSTR pszName, LPCWSTR pszType, void **dataOut, int *cx, int *cy, BOOL fPremultiply)
- {
- UINT errorCode = 0;
- HRSRC res = FindResourceW(hInstance, pszName, pszType);
- if (NULL == res)
- {
- errorCode = GetLastError();
- return HRESULT_FROM_WIN32(errorCode);
- }
-
- HRESULT hr;
- HANDLE handle = LoadResource(hInstance, res);
- if (NULL == handle)
- {
- errorCode = GetLastError();
- hr = HRESULT_FROM_WIN32(errorCode);
- }
- else
- {
- UINT resourceSize = SizeofResource(hInstance, res);
- if (0 == resourceSize)
- {
- errorCode = GetLastError();
- hr = HRESULT_FROM_WIN32(errorCode);
- }
- else
- {
- void *resourceData = LockResource(handle);
- if (NULL == resourceData)
- hr = E_OUTOFMEMORY;
- else
- hr = PngLoader_LoadResourceData(resourceData, resourceSize, dataOut, cx, cy, fPremultiply);
- }
- FreeResource(handle);
- }
- return hr;
- }
- static HRESULT PngLoader_ParseResProtocol(LPWSTR pszAddress, LPCWSTR defaultType, HINSTANCE *module, LPCWSTR *resourceName, LPCWSTR *resourceType)
- {
- if (NULL == module || NULL == resourceName || NULL == resourceType)
- return E_POINTER;
- if (NULL == pszAddress || L'\0' == *pszAddress)
- return E_INVALIDARG;
- INT cchAddress = lstrlenW(pszAddress);
- const WCHAR szPrefix[] = L"res://";
- INT cchPrefix = ARRAYSIZE(szPrefix) - 1;
- if (cchAddress <= cchPrefix)
- return S_FALSE;
- if (CSTR_EQUAL != CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, pszAddress, cchPrefix, szPrefix, cchPrefix))
- return S_FALSE;
- pszAddress += cchPrefix;
- cchAddress -= cchPrefix;
- LPWSTR resType = NULL;
- LPWSTR resName = NULL;
- LPWSTR p = pszAddress + cchAddress;
- while (p != pszAddress && L'/' != *p) p--;
- if (p != pszAddress && p < (pszAddress + cchAddress))
- {
- resName = p + 1;
- *p = L'\0';
- p--;
- }
-
- if (NULL == resName || L'\0' == *resName)
- return E_FAIL;
- while (p != pszAddress && L'/' != *p) p--;
- if (p != pszAddress && p < resName)
- {
- resType = p + 1;
- if (L'\0' == *resType)
- {
- resType = NULL;
- }
- else
- {
- resType = p + 1;
- *p = L'\0';
- p--;
- }
- }
- HINSTANCE hModule = LoadLibraryExW(pszAddress, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
- if (NULL == hModule)
- {
- UINT errorCode = GetLastError();
- if (NULL != resType)
- {
- *(resType - 1) = L'/';
- resType = NULL;
- hModule = LoadLibraryExW(pszAddress, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
- if (NULL == hModule) errorCode = GetLastError();
- }
- if (ERROR_SUCCESS != errorCode)
- return HRESULT_FROM_WIN32(errorCode);
- }
- if (NULL == resType)
- resType = (LPWSTR)defaultType;
- if (NULL != resType && FALSE == IS_INTRESOURCE(resType) && L'#' == *resType)
- {
- INT typeId = 0;
- if (FALSE != StrToIntExW(resType + 1, STIF_DEFAULT, &typeId))
- resType = MAKEINTRESOURCEW(typeId);
- }
- if (NULL != resName && FALSE == IS_INTRESOURCE(resName) && L'#' == *resName)
- {
- INT nameId;
- if (FALSE != StrToIntExW(resName + 1, STIF_DEFAULT, &nameId))
- resName = MAKEINTRESOURCEW(nameId);
- }
- *module = hModule;
- *resourceName = resName;
- *resourceType = resType;
- return S_OK;
- }
- static HRESULT PngLoader_LoadFromFile(LPWSTR pszPath, void **dataOut, int *cx, int *cy, BOOL fPremultiply)
- {
- HINSTANCE resModule = NULL;
- LPCWSTR resName = NULL, resType = NULL;
- HRESULT hr = PngLoader_ParseResProtocol(pszPath, RT_RCDATA, &resModule, &resName, &resType);
- if (S_OK == hr)
- return PngLoader_LoadFromResource(resModule, resName, resType, dataOut, cx, cy, fPremultiply);
- if (FAILED(hr))
- return hr;
- UINT errorCode = 0;
- HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
- if (INVALID_HANDLE_VALUE == hFile)
- {
- errorCode = GetLastError();
- return HRESULT_FROM_WIN32(errorCode);
- }
- UINT resourceSize = GetFileSize(hFile, NULL);
- if (INVALID_FILE_SIZE == resourceSize)
- {
- errorCode = GetLastError();
- hr = HRESULT_FROM_WIN32(errorCode);
- }
- else
- {
- void *resourceData = malloc(resourceSize);
- if (NULL == resourceData)
- hr = E_OUTOFMEMORY;
- else
- {
- DWORD readed = 0;
- if (0 == ReadFile(hFile, resourceData, resourceSize, &readed, NULL) || resourceSize != readed)
- {
- errorCode = GetLastError();
- hr = HRESULT_FROM_WIN32(errorCode);
- }
- else
- {
- hr = PngLoader_LoadResourceData(resourceData, resourceSize, dataOut, cx, cy, fPremultiply);
- }
- free(resourceData);
- }
- }
- CloseHandle(hFile);
- return hr;
- }
- HRESULT PngLoader::LoadData(int *widthOut, int *heightOut, void** dataOut)
- {
- if (NULL == dataOut)
- return E_POINTER;
- *dataOut = NULL;
- return (NULL == instance && !IS_INTRESOURCE(name))?
- PngLoader_LoadFromFile(name, dataOut, widthOut, heightOut, (0 != (flagPremultiply & flags))) :
- PngLoader_LoadFromResource(instance, name, RT_RCDATA, dataOut, widthOut, heightOut, (0 != (flagPremultiply & flags)));
- }
- HRESULT PngLoader::FreeData(void *data)
- {
- if (NULL == data)
- return S_FALSE;
- ifc_wasabihelper *wasabi = NULL;
- HRESULT hr = Plugin_GetWasabiHelper(&wasabi);
- if (SUCCEEDED(hr) && wasabi != NULL)
- {
- api_memmgr *memoryManager = NULL;
- hr = wasabi->GetMemoryManager(&memoryManager);
- if (SUCCEEDED(hr) && memoryManager != NULL)
- {
- memoryManager->sysFree(data);
- memoryManager->Release();
- }
- wasabi->Release();
- }
- return hr;
- }
- HRESULT PngLoader::LoadBitmapEx(HBITMAP *bitmapOut, BITMAPINFOHEADER *headerInfo, void **dataOut)
- {
- INT imageCX, imageCY;
-
- if(NULL == bitmapOut) return E_POINTER;
- void *data = NULL;
- HRESULT hr = LoadData(&imageCX, &imageCY, &data);
- if (FAILED(hr)) return hr;
- ZeroMemory(headerInfo, sizeof(BITMAPINFOHEADER));
- headerInfo->biSize = sizeof(BITMAPINFOHEADER);
- headerInfo->biCompression = BI_RGB;
- headerInfo->biBitCount = 32;
- headerInfo->biPlanes = 1;
- headerInfo->biWidth = imageCX;
- headerInfo->biHeight = -imageCY;
- *bitmapOut = CreateDIBSection(NULL, (LPBITMAPINFO)headerInfo, DIB_RGB_COLORS, dataOut, NULL, 0);
- if (NULL != (*bitmapOut))
- {
- CopyMemory((*dataOut), data, headerInfo->biWidth * abs(headerInfo->biHeight) * sizeof(DWORD));
- }
- else
- {
- *dataOut = NULL;
- hr = E_FAIL;
- }
- FreeData(data);
- return hr;
- }
- HRESULT PngLoader::LoadBitmap(HBITMAP *bitmapOut, int *widthOut, int *heightOut)
- {
- BITMAPINFOHEADER header = {0};
- void *pixelData = NULL;
- if(NULL == bitmapOut) return E_POINTER;
- HRESULT hr = LoadBitmapEx(bitmapOut, &header, &pixelData);
- if (SUCCEEDED(hr))
- {
- if (NULL != widthOut) *widthOut = header.biWidth;
- if (NULL != heightOut) *heightOut = header.biHeight;
- }
- else
- {
- if (NULL != widthOut) *widthOut = 0;
- if (NULL != heightOut) *heightOut = 0;
- }
- return hr;
- }
- #define CBCLASS PngLoader
- START_DISPATCH;
- CB(ADDREF, AddRef);
- CB(RELEASE, Release);
- CB(QUERYINTERFACE, QueryInterface);
- CB(API_LOADDATA, LoadData);
- CB(API_FREEDATA, FreeData);
- CB(API_LOADBITMAP, LoadBitmap);
- CB(API_LOADBITMAPEX, LoadBitmapEx);
- END_DISPATCH;
- #undef CBCLASS
|