Module: wine Branch: master Commit: e502fafd69a2a4c507ad2c5ef9fe5d79b82808f1 URL: http://source.winehq.org/git/wine.git/?a=commit;h=e502fafd69a2a4c507ad2c5ef9...
Author: Damjan Jovanovic damjan.jov@gmail.com Date: Wed Sep 22 22:14:04 2010 +0200
winemenubuilder: Isolate the platform-specific icon generation code.
---
programs/winemenubuilder/winemenubuilder.c | 160 +++++++++++++++++----------- 1 files changed, 99 insertions(+), 61 deletions(-)
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c index dcf13ac..37ebd06 100644 --- a/programs/winemenubuilder/winemenubuilder.c +++ b/programs/winemenubuilder/winemenubuilder.c @@ -770,85 +770,123 @@ static HRESULT open_icon(LPCWSTR filename, int index, BOOL bWait, IStream **ppSt return hr; }
-/* extract an icon from an exe or icon file; helper for IPersistFile_fnSave */ -static char *extract_icon( LPCWSTR path, int index, const char *destFilename, BOOL bWait ) +static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, + int bestIndex, LPCWSTR icoPathW, + const char *destFilename, char **nativeIdentifier) { + char *icoPathA = NULL; + char *iconsDir = NULL; + char *pngPath = NULL; unsigned short crc; - char *iconsdir = NULL, *ico_path = NULL, *ico_name, *png_path = NULL; - char* s; - int n; - IStream *stream = NULL; - HRESULT hr; + char *p, *q; + HRESULT hr = S_OK; + LARGE_INTEGER zero;
- /* Where should we save the icon? */ - WINE_TRACE("path=[%s] index=%d\n", wine_dbgstr_w(path), index); - iconsdir = heap_printf("%s/icons", xdg_data_dir); - if (iconsdir) + icoPathA = wchars_to_utf8_chars(icoPathW); + if (icoPathA == NULL) { - if (mkdir(iconsdir, 0777) && errno != EEXIST) - { - WINE_WARN("couldn't make icons directory %s\n", wine_dbgstr_a(iconsdir)); - goto end; - } + hr = E_OUTOFMEMORY; + goto end; } + crc = crc16(icoPathA); + p = strrchr(icoPathA, '\'); + if (p == NULL) + p = icoPathA; else { - WINE_TRACE("no icon created\n"); - return NULL; - } - - /* Determine the icon base name */ - n = WideCharToMultiByte(CP_UNIXCP, 0, path, -1, NULL, 0, NULL, NULL); - ico_path = HeapAlloc(GetProcessHeap(), 0, n); - WideCharToMultiByte(CP_UNIXCP, 0, path, -1, ico_path, n, NULL, NULL); - s=ico_name=ico_path; - while (*s!='\0') { - if (*s=='/' || *s=='\') { - *s='\'; - ico_name=s; - } else { - *s=tolower(*s); - } - s++; + *p = 0; + p++; } - if (*ico_name=='\') *ico_name++='\0'; - s=strrchr(ico_name,'.'); - if (s) *s='\0'; - - /* Compute the source-path hash */ - crc=crc16(ico_path); - + q = strrchr(p, '.'); + if (q) + *q = 0; if (destFilename) - png_path=heap_printf("%s/%s.png",iconsdir,destFilename); + *nativeIdentifier = heap_printf("%s", destFilename); else - png_path=heap_printf("%s/%04x_%s.%d.png",iconsdir,crc,ico_name,index); - if (png_path == NULL) + *nativeIdentifier = heap_printf("%04X_%s.%d", crc, p, exeIndex); + if (*nativeIdentifier == NULL) { - WINE_ERR("could not extract icon %s, out of memory\n", wine_dbgstr_a(ico_name)); - return NULL; + hr = E_OUTOFMEMORY; + goto end; } - - hr = open_icon( path, index, bWait, &stream ); - if (SUCCEEDED(hr)) + iconsDir = heap_printf("%s/icons", xdg_data_dir); + if (iconsDir == NULL) { - hr = write_native_icon( stream, png_path, path ); - if (SUCCEEDED(hr)) - goto end; - else - WINE_ERR("writing native icon for %s index %d failed, hr=0x%08X\n", wine_dbgstr_w(path), index, hr); + hr = E_OUTOFMEMORY; + goto end; } - else - WINE_WARN("extracting icon %s index %d failed, hr=0x%08X\n", wine_dbgstr_w(path), index, hr); + create_directories(iconsDir); + pngPath = heap_printf("%s/%s.png", iconsDir, *nativeIdentifier); + if (pngPath == NULL) + { + hr = E_OUTOFMEMORY; + goto end; + } + zero.QuadPart = 0; + hr = IStream_Seek(icoStream, zero, STREAM_SEEK_SET, NULL); + if (FAILED(hr)) + goto end; + hr = convert_to_native_icon(icoStream, &bestIndex, 1, &CLSID_WICPngEncoder, + pngPath, icoPathW);
- HeapFree( GetProcessHeap(), 0, png_path ); - png_path=NULL; +end: + HeapFree(GetProcessHeap(), 0, icoPathA); + HeapFree(GetProcessHeap(), 0, iconsDir); + HeapFree(GetProcessHeap(), 0, pngPath); + return hr; +} + +/* extract an icon from an exe or icon file; helper for IPersistFile_fnSave */ +static char *extract_icon(LPCWSTR icoPathW, int index, const char *destFilename, BOOL bWait) +{ + IStream *stream = NULL; + HRESULT hr; + char *nativeIdentifier = NULL; + ICONDIRENTRY *iconDirEntries = NULL; + int numEntries; + int bestIndex = -1; + int maxPixels = 0; + int maxBits = 0; + int i; + + WINE_TRACE("path=[%s] index=%d destFilename=[%s]\n", wine_dbgstr_w(icoPathW), index, wine_dbgstr_a(destFilename)); + + hr = open_icon(icoPathW, index, bWait, &stream); + if (FAILED(hr)) + { + WINE_WARN("opening icon %s index %d failed, hr=0x%08X\n", wine_dbgstr_w(icoPathW), index, hr); + goto end; + } + hr = read_ico_direntries(stream, &iconDirEntries, &numEntries); + if (FAILED(hr)) + goto end; + for (i = 0; i < numEntries; i++) + { + WINE_TRACE("[%d]: %d x %d @ %d\n", i, iconDirEntries[i].bWidth, + iconDirEntries[i].bHeight, iconDirEntries[i].wBitCount); + if (iconDirEntries[i].wBitCount >= maxBits && + (iconDirEntries[i].bHeight * iconDirEntries[i].bWidth) >= maxPixels) + { + bestIndex = i; + maxPixels = iconDirEntries[i].bHeight * iconDirEntries[i].bWidth; + maxBits = iconDirEntries[i].wBitCount; + } + } + WINE_TRACE("Selected: %d\n", bestIndex); + hr = platform_write_icon(stream, index, bestIndex, icoPathW, destFilename, &nativeIdentifier); + if (FAILED(hr)) + WINE_WARN("writing icon failed, error 0x%08X\n", hr);
- end: - HeapFree(GetProcessHeap(), 0, iconsdir); - HeapFree(GetProcessHeap(), 0, ico_path); +end: if (stream) IStream_Release(stream); - return png_path; + HeapFree(GetProcessHeap(), 0, iconDirEntries); + if (FAILED(hr)) + { + HeapFree(GetProcessHeap(), 0, nativeIdentifier); + nativeIdentifier = NULL; + } + return nativeIdentifier; }
static HKEY open_menus_reg_key(void)