Damjan Jovanovic : winemenubuilder: Isolate the platform-specific icon generation code.

Alexandre Julliard julliard at winehq.org
Thu Sep 23 12:43:49 CDT 2010


Module: wine
Branch: master
Commit: e502fafd69a2a4c507ad2c5ef9fe5d79b82808f1
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e502fafd69a2a4c507ad2c5ef9fe5d79b82808f1

Author: Damjan Jovanovic <damjan.jov at 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)




More information about the wine-cvs mailing list