winemenubuilder: Isolate the platform-specific icon generation code.
This commit is contained in:
parent
6e46e9048f
commit
e502fafd69
|
@ -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;
|
||||
char *p, *q;
|
||||
HRESULT hr = S_OK;
|
||||
LARGE_INTEGER zero;
|
||||
|
||||
icoPathA = wchars_to_utf8_chars(icoPathW);
|
||||
if (icoPathA == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto end;
|
||||
}
|
||||
crc = crc16(icoPathA);
|
||||
p = strrchr(icoPathA, '\\');
|
||||
if (p == NULL)
|
||||
p = icoPathA;
|
||||
else
|
||||
{
|
||||
*p = 0;
|
||||
p++;
|
||||
}
|
||||
q = strrchr(p, '.');
|
||||
if (q)
|
||||
*q = 0;
|
||||
if (destFilename)
|
||||
*nativeIdentifier = heap_printf("%s", destFilename);
|
||||
else
|
||||
*nativeIdentifier = heap_printf("%04X_%s.%d", crc, p, exeIndex);
|
||||
if (*nativeIdentifier == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto end;
|
||||
}
|
||||
iconsDir = heap_printf("%s/icons", xdg_data_dir);
|
||||
if (iconsDir == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto end;
|
||||
}
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
/* 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)
|
||||
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))
|
||||
{
|
||||
if (mkdir(iconsdir, 0777) && errno != EEXIST)
|
||||
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)
|
||||
{
|
||||
WINE_WARN("couldn't make icons directory %s\n", wine_dbgstr_a(iconsdir));
|
||||
goto end;
|
||||
bestIndex = i;
|
||||
maxPixels = iconDirEntries[i].bHeight * iconDirEntries[i].bWidth;
|
||||
maxBits = iconDirEntries[i].wBitCount;
|
||||
}
|
||||
}
|
||||
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++;
|
||||
}
|
||||
if (*ico_name=='\\') *ico_name++='\0';
|
||||
s=strrchr(ico_name,'.');
|
||||
if (s) *s='\0';
|
||||
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);
|
||||
|
||||
/* Compute the source-path hash */
|
||||
crc=crc16(ico_path);
|
||||
|
||||
if (destFilename)
|
||||
png_path=heap_printf("%s/%s.png",iconsdir,destFilename);
|
||||
else
|
||||
png_path=heap_printf("%s/%04x_%s.%d.png",iconsdir,crc,ico_name,index);
|
||||
if (png_path == NULL)
|
||||
{
|
||||
WINE_ERR("could not extract icon %s, out of memory\n", wine_dbgstr_a(ico_name));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hr = open_icon( path, index, bWait, &stream );
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
WINE_WARN("extracting icon %s index %d failed, hr=0x%08X\n", wine_dbgstr_w(path), index, hr);
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, png_path );
|
||||
png_path=NULL;
|
||||
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue