2024-06-03 15:30:46 -07:00
|
|
|
From 3814dcc3cbbb1ffde8a208cf6612f8230703401a Mon Sep 17 00:00:00 2001
|
2018-12-02 13:51:29 -08:00
|
|
|
From: =?UTF-8?q?Gabriel=20Iv=C4=83ncescu?= <gabrielopcode@gmail.com>
|
|
|
|
Date: Fri, 30 Nov 2018 12:20:40 +0200
|
|
|
|
Subject: [PATCH] shell32/iconcache: Generate icons from available icons if
|
|
|
|
some icon sizes failed to load
|
|
|
|
MIME-Version: 1.0
|
|
|
|
Content-Type: text/plain; charset=UTF-8
|
|
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
|
|
|
|
For icon sizes that fail to load, create them from another icon that
|
|
|
|
succeeded by resizing it, favoring icons that are the closest and larger
|
|
|
|
(to reduce pixelation artefacts) and with the closest aspect ratio as the
|
|
|
|
source of this operation (to be as generic as possible). For example, if
|
|
|
|
the icon that needs to be created must be 16x16, an 18x18 icon would get
|
|
|
|
picked over either a 32x32 (it's further from 16x16) or a 15x15 (icons
|
|
|
|
larger than 16x16 are favored since they're larger than the result, so
|
|
|
|
smaller icons are only picked if no other available icon is larger).
|
|
|
|
|
|
|
|
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45696
|
|
|
|
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
|
|
|
|
---
|
2024-06-03 15:30:46 -07:00
|
|
|
dlls/shell32/iconcache.c | 75 ++++++++++++++++++++++++++++++++--------
|
|
|
|
1 file changed, 60 insertions(+), 15 deletions(-)
|
2018-12-02 13:51:29 -08:00
|
|
|
|
|
|
|
diff --git a/dlls/shell32/iconcache.c b/dlls/shell32/iconcache.c
|
2024-06-03 15:30:46 -07:00
|
|
|
index e3ae2499fe9..f60787406c4 100644
|
2018-12-02 13:51:29 -08:00
|
|
|
--- a/dlls/shell32/iconcache.c
|
|
|
|
+++ b/dlls/shell32/iconcache.c
|
2021-09-17 15:45:25 -07:00
|
|
|
@@ -21,6 +21,7 @@
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
+#include <math.h>
|
|
|
|
|
|
|
|
#define COBJMACROS
|
|
|
|
|
2024-06-03 15:30:46 -07:00
|
|
|
@@ -333,17 +334,6 @@ static INT SIC_IconAppend (const WCHAR *sourcefile, INT src_index, HICON *hicons
|
2018-12-02 13:51:29 -08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
-static BOOL get_imagelist_icon_size(int list, SIZE *size)
|
|
|
|
-{
|
2022-02-02 16:11:23 -08:00
|
|
|
- int cx, cy;
|
2018-12-02 13:51:29 -08:00
|
|
|
- if (list < 0 || list >= ARRAY_SIZE(shell_imagelists)) return FALSE;
|
|
|
|
-
|
2022-02-02 16:11:23 -08:00
|
|
|
- if (!ImageList_GetIconSize( shell_imagelists[list], &cx, &cy )) return FALSE;
|
|
|
|
- size->cx = cx;
|
|
|
|
- size->cy = cy;
|
|
|
|
- return TRUE;
|
2018-12-02 13:51:29 -08:00
|
|
|
-}
|
|
|
|
-
|
|
|
|
/****************************************************************************
|
|
|
|
* SIC_LoadIcon [internal]
|
|
|
|
*
|
2024-06-03 15:30:46 -07:00
|
|
|
@@ -354,15 +344,70 @@ static INT SIC_LoadIcon (const WCHAR *sourcefile, INT index, DWORD flags)
|
2018-12-02 13:51:29 -08:00
|
|
|
{
|
|
|
|
HICON hicons[ARRAY_SIZE(shell_imagelists)] = { 0 };
|
|
|
|
HICON hshortcuts[ARRAY_SIZE(hicons)] = { 0 };
|
|
|
|
+ SIZE size[ARRAY_SIZE(shell_imagelists)];
|
|
|
|
unsigned int i;
|
|
|
|
- SIZE size;
|
|
|
|
INT ret = -1;
|
2024-06-03 15:30:46 -07:00
|
|
|
+ INT x, y;
|
2018-12-02 13:51:29 -08:00
|
|
|
|
|
|
|
+ /* Keep track of the sizes in case any icon fails to get extracted */
|
2021-09-17 15:45:25 -07:00
|
|
|
for (i = 0; i < ARRAY_SIZE(hicons); i++)
|
|
|
|
{
|
2022-02-02 16:11:23 -08:00
|
|
|
- if (!get_imagelist_icon_size( i, &size ) ||
|
|
|
|
- !PrivateExtractIconsW( sourcefile, index, size.cx, size.cy, &hicons[i], 0, 1, 0 ))
|
2021-09-17 15:45:25 -07:00
|
|
|
- WARN("Failed to load icon %d from %s.\n", index, debugstr_w(sourcefile));
|
2024-06-03 15:30:46 -07:00
|
|
|
+ ImageList_GetIconSize(shell_imagelists[i], &x, &y);
|
|
|
|
+ size[i].cx = x;
|
|
|
|
+ size[i].cy = y;
|
2018-12-02 13:51:29 -08:00
|
|
|
+ PrivateExtractIconsW(sourcefile, index, size[i].cx, size[i].cy, &hicons[i], 0, 1, 0);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Fill any icon handles that failed to get extracted, by resizing
|
|
|
|
+ another icon handle that succeeded and creating the icon from it.
|
|
|
|
+ Use a dumb O(n^2) algorithm since ARRAY_SIZE(hicons) is small */
|
2021-09-17 15:45:25 -07:00
|
|
|
+ for (i = 0; i < ARRAY_SIZE(hicons); i++)
|
|
|
|
+ {
|
2018-12-02 13:51:29 -08:00
|
|
|
+ unsigned int k, ix, iy;
|
|
|
|
+ BOOL failed = TRUE;
|
|
|
|
+ if (hicons[i]) continue;
|
|
|
|
+
|
|
|
|
+ for (k = 0; k < ARRAY_SIZE(hicons); k++)
|
|
|
|
+ {
|
|
|
|
+ if (hicons[k])
|
|
|
|
+ {
|
|
|
|
+ ix = iy = k;
|
|
|
|
+ failed = FALSE;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (failed) goto fail;
|
|
|
|
+
|
|
|
|
+ for (k++; k < ARRAY_SIZE(hicons); k++)
|
|
|
|
+ {
|
|
|
|
+ if (!hicons[k]) continue;
|
|
|
|
+
|
|
|
|
+ /* Find closest-sized icon, but favor larger icons to resize from */
|
|
|
|
+ if (size[k].cx >= size[i].cx)
|
|
|
|
+ ix = (size[ix].cx < size[i].cx || size[ix].cx > size[k].cx) ? k : ix;
|
|
|
|
+ else
|
|
|
|
+ ix = (size[ix].cx < size[i].cx && size[ix].cx < size[k].cx) ? k : ix;
|
|
|
|
+
|
|
|
|
+ if (size[k].cy >= size[i].cy)
|
|
|
|
+ iy = (size[iy].cy < size[i].cy || size[iy].cy > size[k].cy) ? k : iy;
|
|
|
|
+ else
|
|
|
|
+ iy = (size[iy].cy < size[i].cy && size[iy].cy < size[k].cy) ? k : iy;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Use the closest icon in aspect ratio if ix and iy differ */
|
|
|
|
+ if (ix != iy)
|
|
|
|
+ {
|
|
|
|
+ float i_ratio, ix_ratio, iy_ratio;
|
|
|
|
+ i_ratio = (float)size[i].cx / (float)size[i].cy;
|
|
|
|
+ ix_ratio = (float)size[ix].cx / (float)size[ix].cy;
|
|
|
|
+ iy_ratio = (float)size[iy].cx / (float)size[iy].cy;
|
|
|
|
+ if (fabsf(ix_ratio - i_ratio) > fabsf(iy_ratio - i_ratio))
|
|
|
|
+ ix = iy;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* If this fails, we have to abort to prevent the image lists from
|
|
|
|
+ becoming out of sync and completely screwing the icons up */
|
|
|
|
+ hicons[i] = CopyImage(hicons[ix], IMAGE_ICON, size[i].cx, size[i].cy, 0);
|
|
|
|
if (!hicons[i]) goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
--
|
2024-06-03 15:30:46 -07:00
|
|
|
2.43.0
|
2018-12-02 13:51:29 -08:00
|
|
|
|