aboutsummaryrefslogtreecommitdiff
path: root/Src/omBrowser/pngLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/omBrowser/pngLoader.cpp')
-rw-r--r--Src/omBrowser/pngLoader.cpp360
1 files changed, 360 insertions, 0 deletions
diff --git a/Src/omBrowser/pngLoader.cpp b/Src/omBrowser/pngLoader.cpp
new file mode 100644
index 00000000..abc1c288
--- /dev/null
+++ b/Src/omBrowser/pngLoader.cpp
@@ -0,0 +1,360 @@
+#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 \ No newline at end of file