winemenubuilder: On Mac OS X, keep multiple icon sizes.

ICNS files can store multiple sizes, like ICOs.
This commit is contained in:
Ken Thomases 2011-01-05 04:57:18 -06:00 committed by Alexandre Julliard
parent 92e439b0f0
commit 53ba89c967
1 changed files with 91 additions and 29 deletions

View File

@ -815,10 +815,35 @@ static HRESULT open_icon(LPCWSTR filename, int index, BOOL bWait, IStream **ppSt
} }
#ifdef __APPLE__ #ifdef __APPLE__
static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, #define ICNS_SLOTS 6
int bestIndex, LPCWSTR icoPathW,
static inline int size_to_slot(int size)
{
switch (size)
{
case 16: return 0;
case 32: return 1;
case 48: return 2;
case 128: return 3;
case 256: return 4;
case 512: return 5;
}
return -1;
}
static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, LPCWSTR icoPathW,
const char *destFilename, char **nativeIdentifier) const char *destFilename, char **nativeIdentifier)
{ {
ICONDIRENTRY *iconDirEntries = NULL;
int numEntries;
struct {
int index;
int maxPixels;
int maxBits;
} best[ICNS_SLOTS];
int indexes[ICNS_SLOTS];
int i;
GUID guid; GUID guid;
WCHAR *guidStrW = NULL; WCHAR *guidStrW = NULL;
char *guidStrA = NULL; char *guidStrA = NULL;
@ -826,6 +851,42 @@ static HRESULT platform_write_icon(IStream *icoStream, int exeIndex,
LARGE_INTEGER zero; LARGE_INTEGER zero;
HRESULT hr; HRESULT hr;
hr = read_ico_direntries(icoStream, &iconDirEntries, &numEntries);
if (FAILED(hr))
goto end;
for (i = 0; i < ICNS_SLOTS; i++)
{
best[i].index = -1;
best[i].maxPixels = 0;
best[i].maxBits = 0;
}
for (i = 0; i < numEntries; i++)
{
int slot;
WINE_TRACE("[%d]: %d x %d @ %d\n", i, iconDirEntries[i].bWidth,
iconDirEntries[i].bHeight, iconDirEntries[i].wBitCount);
slot = size_to_slot(iconDirEntries[i].bWidth);
if (slot < 0)
continue;
if (iconDirEntries[i].wBitCount >= best[slot].maxBits &&
(iconDirEntries[i].bHeight * iconDirEntries[i].bWidth) >= best[slot].maxPixels)
{
best[slot].index = i;
best[slot].maxPixels = iconDirEntries[i].bHeight * iconDirEntries[i].bWidth;
best[slot].maxBits = iconDirEntries[i].wBitCount;
}
}
numEntries = 0;
for (i = 0; i < ICNS_SLOTS; i++)
{
if (best[i].index >= 0)
{
indexes[numEntries] = best[i].index;
numEntries++;
}
}
hr = CoCreateGuid(&guid); hr = CoCreateGuid(&guid);
if (FAILED(hr)) if (FAILED(hr))
{ {
@ -859,7 +920,7 @@ static HRESULT platform_write_icon(IStream *icoStream, int exeIndex,
WINE_WARN("seeking icon stream failed, error 0x%08X\n", hr); WINE_WARN("seeking icon stream failed, error 0x%08X\n", hr);
goto end; goto end;
} }
hr = convert_to_native_icon(icoStream, &bestIndex, 1, &CLSID_WICIcnsEncoder, hr = convert_to_native_icon(icoStream, indexes, numEntries, &CLSID_WICIcnsEncoder,
icnsPath, icoPathW); icnsPath, icoPathW);
if (FAILED(hr)) if (FAILED(hr))
{ {
@ -869,6 +930,7 @@ static HRESULT platform_write_icon(IStream *icoStream, int exeIndex,
} }
end: end:
HeapFree(GetProcessHeap(), 0, iconDirEntries);
CoTaskMemFree(guidStrW); CoTaskMemFree(guidStrW);
HeapFree(GetProcessHeap(), 0, guidStrA); HeapFree(GetProcessHeap(), 0, guidStrA);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
@ -878,10 +940,15 @@ end:
return hr; return hr;
} }
#else #else
static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, LPCWSTR icoPathW,
int bestIndex, LPCWSTR icoPathW,
const char *destFilename, char **nativeIdentifier) const char *destFilename, char **nativeIdentifier)
{ {
ICONDIRENTRY *iconDirEntries = NULL;
int numEntries;
int bestIndex = -1;
int maxPixels = 0;
int maxBits = 0;
int i;
char *icoPathA = NULL; char *icoPathA = NULL;
char *iconsDir = NULL; char *iconsDir = NULL;
char *pngPath = NULL; char *pngPath = NULL;
@ -890,6 +957,23 @@ static HRESULT platform_write_icon(IStream *icoStream, int exeIndex,
HRESULT hr = S_OK; HRESULT hr = S_OK;
LARGE_INTEGER zero; LARGE_INTEGER zero;
hr = read_ico_direntries(icoStream, &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);
icoPathA = wchars_to_utf8_chars(icoPathW); icoPathA = wchars_to_utf8_chars(icoPathW);
if (icoPathA == NULL) if (icoPathA == NULL)
{ {
@ -938,6 +1022,7 @@ static HRESULT platform_write_icon(IStream *icoStream, int exeIndex,
pngPath, icoPathW); pngPath, icoPathW);
end: end:
HeapFree(GetProcessHeap(), 0, iconDirEntries);
HeapFree(GetProcessHeap(), 0, icoPathA); HeapFree(GetProcessHeap(), 0, icoPathA);
HeapFree(GetProcessHeap(), 0, iconsDir); HeapFree(GetProcessHeap(), 0, iconsDir);
HeapFree(GetProcessHeap(), 0, pngPath); HeapFree(GetProcessHeap(), 0, pngPath);
@ -951,12 +1036,6 @@ static char *extract_icon(LPCWSTR icoPathW, int index, const char *destFilename,
IStream *stream = NULL; IStream *stream = NULL;
HRESULT hr; HRESULT hr;
char *nativeIdentifier = NULL; 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)); WINE_TRACE("path=[%s] index=%d destFilename=[%s]\n", wine_dbgstr_w(icoPathW), index, wine_dbgstr_a(destFilename));
@ -966,30 +1045,13 @@ static char *extract_icon(LPCWSTR icoPathW, int index, const char *destFilename,
WINE_WARN("opening icon %s index %d failed, hr=0x%08X\n", wine_dbgstr_w(icoPathW), index, hr); WINE_WARN("opening icon %s index %d failed, hr=0x%08X\n", wine_dbgstr_w(icoPathW), index, hr);
goto end; goto end;
} }
hr = read_ico_direntries(stream, &iconDirEntries, &numEntries); hr = platform_write_icon(stream, index, icoPathW, destFilename, &nativeIdentifier);
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)) if (FAILED(hr))
WINE_WARN("writing icon failed, error 0x%08X\n", hr); WINE_WARN("writing icon failed, error 0x%08X\n", hr);
end: end:
if (stream) if (stream)
IStream_Release(stream); IStream_Release(stream);
HeapFree(GetProcessHeap(), 0, iconDirEntries);
if (FAILED(hr)) if (FAILED(hr))
{ {
HeapFree(GetProcessHeap(), 0, nativeIdentifier); HeapFree(GetProcessHeap(), 0, nativeIdentifier);