Skip to content

Commit e1f11c9

Browse files
committed
Rewrite the algorithm that sets smallIcon/largeIcon in Decorations class
Don't sort, compare and keep the image that is closest to the desired dimensions, pixel transparency and pixel depth. The new method "isCloserThan" is based on the (now deleted) "compare" method and returns true only if "compare" would have returned -1 Reduce visibility of Decorations::setImages
1 parent 7f381e8 commit e1f11c9

File tree

1 file changed

+70
-58
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets

1 file changed

+70
-58
lines changed

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Decorations.java

Lines changed: 70 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -274,26 +274,6 @@ void closeWidget () {
274274
if (event.doit && !isDisposed ()) dispose ();
275275
}
276276

277-
int compare (ImageData data1, ImageData data2, int width, int height, int depth) {
278-
int value1 = Math.abs (data1.width - width), value2 = Math.abs (data2.width - width);
279-
if (value1 == value2) {
280-
int transparent1 = data1.getTransparencyType ();
281-
int transparent2 = data2.getTransparencyType ();
282-
if (transparent1 == transparent2) {
283-
if (data1.depth == data2.depth) return 0;
284-
return data1.depth > data2.depth && data1.depth <= depth ? -1 : 1;
285-
}
286-
if (transparent1 == SWT.TRANSPARENCY_ALPHA) return -1;
287-
if (transparent2 == SWT.TRANSPARENCY_ALPHA) return 1;
288-
if (transparent1 == SWT.TRANSPARENCY_MASK) return -1;
289-
if (transparent2 == SWT.TRANSPARENCY_MASK) return 1;
290-
if (transparent1 == SWT.TRANSPARENCY_PIXEL) return -1;
291-
if (transparent2 == SWT.TRANSPARENCY_PIXEL) return 1;
292-
return 0;
293-
}
294-
return value1 < value2 ? -1 : 1;
295-
}
296-
297277
@Override
298278
Widget computeTabGroup () {
299279
return this;
@@ -882,7 +862,7 @@ public void setImage (Image image) {
882862
setImages (image, null);
883863
}
884864

885-
void setImages (Image image, Image [] images) {
865+
private void setImages (Image image, Image [] images) {
886866
if (smallImage != null) smallImage.dispose ();
887867
if (largeImage != null) largeImage.dispose ();
888868
smallImage = largeImage = null;
@@ -892,23 +872,17 @@ void setImages (Image image, Image [] images) {
892872
smallIcon = largeIcon = image;
893873
} else {
894874
if (images != null && images.length > 0) {
895-
int depth = display.getIconDepth ();
896-
ImageData [] datas = null;
897-
if (images.length > 1) {
898-
Image [] bestImages = new Image [images.length];
899-
System.arraycopy (images, 0, bestImages, 0, images.length);
900-
datas = new ImageData [images.length];
901-
for (int i=0; i<datas.length; i++) {
902-
datas [i] = images [i].getImageData ();
903-
}
904-
images = bestImages;
905-
sort (images, datas, getSystemMetrics (OS.SM_CXSMICON), getSystemMetrics (OS.SM_CYSMICON), depth);
906-
}
907-
smallIcon = images [0];
908-
if (images.length > 1) {
909-
sort (images, datas, getSystemMetrics (OS.SM_CXICON), getSystemMetrics (OS.SM_CYICON), depth);
910-
}
911-
largeIcon = images [0];
875+
int depth = display.getIconDepth();
876+
877+
ImageData[] imageData = getImageDataAt100(images);
878+
879+
int smallIconWidthAt100 = getSystemMetrics(OS.SM_CXSMICON);
880+
int smallIconIndex = findIndexOfClosest(imageData, smallIconWidthAt100, depth);
881+
smallIcon = images[smallIconIndex];
882+
883+
int largeIconWidthAt100 = getSystemMetrics(OS.SM_CXICON);
884+
int largeIconIndex = findIndexOfClosest(imageData, largeIconWidthAt100, depth);
885+
largeIcon = images[largeIconIndex];
912886
}
913887
}
914888
if (smallIcon != null) {
@@ -949,6 +923,64 @@ void setImages (Image image, Image [] images) {
949923
}
950924
}
951925

926+
private static ImageData[] getImageDataAt100(Image[] images) {
927+
ImageData[] datas = new ImageData[images.length];
928+
for (int i = 0; i < images.length; i++) {
929+
datas[i] = images[i].getImageData(100);
930+
}
931+
return datas;
932+
}
933+
934+
private static int findIndexOfClosest(ImageData[] imageData, int targetWidth, int targetDepth) {
935+
int closestIndex = 0;
936+
ImageData closestData = imageData[0];
937+
for (int i = 1; i < imageData.length; i++) {
938+
if (isCloserThan(imageData[i], closestData, targetWidth, targetDepth)) {
939+
closestIndex = i;
940+
closestData = imageData[i];
941+
}
942+
}
943+
944+
return closestIndex;
945+
}
946+
947+
private static boolean isCloserThan(ImageData dataToTest, ImageData referenceData, int targetWidth, int targetDepth) {
948+
int diffWidthToTest = Math.abs(dataToTest.width - targetWidth);
949+
int diffReferenceWidth = Math.abs(referenceData.width - targetWidth);
950+
951+
// The closer the width the better
952+
if (diffWidthToTest != diffReferenceWidth)
953+
return diffWidthToTest < diffReferenceWidth;
954+
955+
int transparencyToTest = dataToTest.getTransparencyType();
956+
int referenceTransparency = referenceData.getTransparencyType();
957+
958+
// If they have the same transparency then the bigger the pixel depth (without
959+
// surpassing the target depth) the better
960+
if (transparencyToTest == referenceTransparency) {
961+
if (dataToTest.depth == referenceData.depth)
962+
return false;
963+
964+
return dataToTest.depth > referenceData.depth && dataToTest.depth <= targetDepth;
965+
}
966+
967+
// If they have different transparency, favor (in this order): the one with
968+
// an alpha channel, the one with a mask, the one with a transparency pixel
969+
if (transparencyToTest == SWT.TRANSPARENCY_ALPHA)
970+
return true;
971+
if (referenceTransparency == SWT.TRANSPARENCY_ALPHA)
972+
return false;
973+
if (transparencyToTest == SWT.TRANSPARENCY_MASK)
974+
return true;
975+
if (referenceTransparency == SWT.TRANSPARENCY_MASK)
976+
return false;
977+
if (transparencyToTest == SWT.TRANSPARENCY_PIXEL)
978+
return true;
979+
if (referenceTransparency == SWT.TRANSPARENCY_PIXEL)
980+
return false;
981+
return false;
982+
}
983+
952984
/**
953985
* Sets the receiver's images to the argument, which may
954986
* be an empty array. Images are typically displayed by the
@@ -1313,26 +1345,6 @@ public void setVisible (boolean visible) {
13131345
}
13141346
}
13151347

1316-
void sort (Image [] images, ImageData [] datas, int width, int height, int depth) {
1317-
/* Shell Sort from K&R, pg 108 */
1318-
int length = images.length;
1319-
if (length <= 1) return;
1320-
for (int gap=length/2; gap>0; gap/=2) {
1321-
for (int i=gap; i<length; i++) {
1322-
for (int j=i-gap; j>=0; j-=gap) {
1323-
if (compare (datas [j], datas [j + gap], width, height, depth) >= 0) {
1324-
Image swap = images [j];
1325-
images [j] = images [j + gap];
1326-
images [j + gap] = swap;
1327-
ImageData swapData = datas [j];
1328-
datas [j] = datas [j + gap];
1329-
datas [j + gap] = swapData;
1330-
}
1331-
}
1332-
}
1333-
}
1334-
}
1335-
13361348
@Override
13371349
boolean translateAccelerator (MSG msg) {
13381350
if (!isEnabled () || !isActive ()) return false;

0 commit comments

Comments
 (0)