From 72c449de252f663cf732771f6d4552951de01589 Mon Sep 17 00:00:00 2001 From: Andreas Koch Date: Wed, 7 May 2025 15:40:27 +0200 Subject: [PATCH] [win32] Reduce calls to Image#win32_getHandle(int) This commit reduces the calls to Image#win32_getHandle(int) in GC. When drawing an image with a GC multiple draw... methods are calling each other for that operation. All those methods are refetching the handle via Image#win32_getHandle(int) with getZoom(). To support use cases where a method uses a different zoom to get a handle to draw the handle is now fetched in the top most methods and are passed to the other methods directly. --- .../win32/org/eclipse/swt/graphics/GC.java | 67 ++++++++++--------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java index 42c527d985f..ddaa6da5964 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java @@ -985,20 +985,20 @@ public void drawImage (Image image, int srcX, int srcY, int srcWidth, int srcHei if (image == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); - int deviceZoom = getZoom(); - Rectangle src = DPIUtil.scaleUp(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight), deviceZoom); - Rectangle dest = DPIUtil.scaleUp(drawable, new Rectangle(destX, destY, destWidth, destHeight), deviceZoom); - if (deviceZoom != 100) { + int imageZoom = getZoom(); + Rectangle src = DPIUtil.scaleUp(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight), imageZoom); + Rectangle dest = DPIUtil.scaleUp(drawable, new Rectangle(destX, destY, destWidth, destHeight), imageZoom); + if (imageZoom != 100) { /* * This is a HACK! Due to rounding errors at fractional scale factors, * the coordinates may be slightly off. The workaround is to restrict * coordinates to the allowed bounds. */ - Rectangle b = image.getBounds(deviceZoom); + Rectangle b = image.getBounds(imageZoom); int errX = src.x + src.width - b.width; int errY = src.y + src.height - b.height; if (errX != 0 || errY != 0) { - if (errX <= deviceZoom / 100 && errY <= deviceZoom / 100) { + if (errX <= imageZoom / 100 && errY <= imageZoom / 100) { src.intersect(b); } else { SWT.error (SWT.ERROR_INVALID_ARGUMENT); @@ -1009,12 +1009,14 @@ public void drawImage (Image image, int srcX, int srcY, int srcWidth, int srcHei } void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) { + int imageZoom = getZoom(); if (data.gdipGraphics != 0) { //TODO - cache bitmap - long [] gdipImage = srcImage.createGdipImage(getZoom()); + long [] gdipImage = srcImage.createGdipImage(imageZoom); long img = gdipImage[0]; int imgWidth = Gdip.Image_GetWidth(img); int imgHeight = Gdip.Image_GetHeight(img); + if (simple) { srcWidth = destWidth = imgWidth; srcHeight = destHeight = imgHeight; @@ -1065,17 +1067,18 @@ void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, } return; } + long imageHandle = Image.win32_getHandle(srcImage, imageZoom); switch (srcImage.type) { case SWT.BITMAP: - drawBitmap(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple); + drawBitmap(srcImage, imageHandle, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple); break; case SWT.ICON: - drawIcon(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple); + drawIcon(imageHandle, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple); break; } } -void drawIcon(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) { +void drawIcon(long imageHandle, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) { int technology = OS.GetDeviceCaps(handle, OS.TECHNOLOGY); boolean drawIcon = true; @@ -1099,14 +1102,14 @@ void drawIcon(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, i /* Simple case: no stretching, entire icon */ if (simple && technology != OS.DT_RASPRINTER && drawIcon) { if (offsetX != 0 || offsetY != 0) OS.SetWindowOrgEx(handle, 0, 0, null); - OS.DrawIconEx(handle, destX - offsetX, destY - offsetY, Image.win32_getHandle(srcImage, getZoom()), 0, 0, 0, 0, flags); + OS.DrawIconEx(handle, destX - offsetX, destY - offsetY, imageHandle, 0, 0, 0, 0, flags); if (offsetX != 0 || offsetY != 0) OS.SetWindowOrgEx(handle, offsetX, offsetY, null); return; } /* Get the icon info */ ICONINFO srcIconInfo = new ICONINFO(); - OS.GetIconInfo(Image.win32_getHandle(srcImage, getZoom()), srcIconInfo); + OS.GetIconInfo(imageHandle, srcIconInfo); /* Get the icon width and height */ long hBitmap = srcIconInfo.hbmColor; @@ -1128,11 +1131,11 @@ void drawIcon(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, i srcWidth == destWidth && srcHeight == destHeight && srcWidth == iconWidth && srcHeight == iconHeight; if (!drawIcon) { - drawBitmapMask(srcImage, srcIconInfo.hbmColor, srcIconInfo.hbmMask, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, iconWidth, iconHeight, false); + drawBitmapMask(srcIconInfo.hbmColor, srcIconInfo.hbmMask, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, iconWidth, iconHeight, false); } else if (simple && technology != OS.DT_RASPRINTER) { /* Simple case: no stretching, entire icon */ if (offsetX != 0 || offsetY != 0) OS.SetWindowOrgEx(handle, 0, 0, null); - OS.DrawIconEx(handle, destX - offsetX, destY - offsetY, Image.win32_getHandle(srcImage, getZoom()), 0, 0, 0, 0, flags); + OS.DrawIconEx(handle, destX - offsetX, destY - offsetY, imageHandle, 0, 0, 0, 0, flags); if (offsetX != 0 || offsetY != 0) OS.SetWindowOrgEx(handle, offsetX, offsetY, null); } else { /* Create the icon info and HDC's */ @@ -1205,9 +1208,9 @@ void drawIcon(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, i if (failed) SWT.error(SWT.ERROR_INVALID_ARGUMENT); } -void drawBitmap(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) { +void drawBitmap(Image srcImage, long imageHandle, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) { BITMAP bm = new BITMAP(); - OS.GetObject(Image.win32_getHandle(srcImage, getZoom()), BITMAP.sizeof, bm); + OS.GetObject(imageHandle, BITMAP.sizeof, bm); int imgWidth = bm.bmWidth; int imgHeight = bm.bmHeight; if (simple) { @@ -1235,19 +1238,19 @@ void drawBitmap(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, boolean isDib = bm.bmBits != 0; int depth = bm.bmPlanes * bm.bmBitsPixel; if (isDib && depth == 32) { - drawBitmapAlpha(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple); + drawBitmapAlpha(imageHandle, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple); } else if (srcImage.transparentPixel != -1) { - drawBitmapTransparent(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight); + drawBitmapTransparent(srcImage, imageHandle, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight); } else { - drawBitmapColor(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple); + drawBitmapColor(imageHandle, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple); } if (mustRestore) { - long hOldBitmap = OS.SelectObject(memGC.handle, Image.win32_getHandle(srcImage, getZoom())); + long hOldBitmap = OS.SelectObject(memGC.handle, imageHandle); memGC.data.hNullBitmap = hOldBitmap; } } -void drawBitmapAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) { +void drawBitmapAlpha(long imageHandle, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) { boolean alphaBlendSupport = true; boolean isPrinter = OS.GetDeviceCaps(handle, OS.TECHNOLOGY) == OS.DT_RASPRINTER; int sourceAlpha = -1; @@ -1255,7 +1258,7 @@ void drawBitmapAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHe int caps = OS.GetDeviceCaps(handle, OS.SHADEBLENDCAPS); if (caps != 0) { long srcHdc = OS.CreateCompatibleDC(handle); - long oldSrcBitmap = OS.SelectObject(srcHdc, Image.win32_getHandle(srcImage, getZoom())); + long oldSrcBitmap = OS.SelectObject(srcHdc, imageHandle); long memDib = Image.createDIB(srcWidth, srcHeight, 32); if (memDib == 0) SWT.error(SWT.ERROR_NO_HANDLES); long memHdc = OS.CreateCompatibleDC(handle); @@ -1282,7 +1285,7 @@ void drawBitmapAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHe if (sourceAlpha != -1) { if (sourceAlpha == 0) return; if (sourceAlpha == 255) { - drawBitmapColor(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple); + drawBitmapColor(imageHandle, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple); return; } alphaBlendSupport = (caps & OS.SB_CONST_ALPHA) != 0; @@ -1296,7 +1299,7 @@ void drawBitmapAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHe BLENDFUNCTION blend = new BLENDFUNCTION(); blend.BlendOp = OS.AC_SRC_OVER; long srcHdc = OS.CreateCompatibleDC(handle); - long oldSrcBitmap = OS.SelectObject(srcHdc, Image.win32_getHandle(srcImage, getZoom())); + long oldSrcBitmap = OS.SelectObject(srcHdc, imageHandle); blend.SourceConstantAlpha = (byte)sourceAlpha; blend.AlphaFormat = OS.AC_SRC_ALPHA; OS.AlphaBlend(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, blend); @@ -1329,7 +1332,7 @@ void drawBitmapAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHe /* Create resources */ long srcHdc = OS.CreateCompatibleDC(handle); - long oldSrcBitmap = OS.SelectObject(srcHdc, Image.win32_getHandle(srcImage, getZoom())); + long oldSrcBitmap = OS.SelectObject(srcHdc, imageHandle); long memHdc = OS.CreateCompatibleDC(handle); long memDib = Image.createDIB(Math.max(srcWidth, destWidth), Math.max(srcHeight, destHeight), 32); if (memDib == 0) SWT.error(SWT.ERROR_NO_HANDLES); @@ -1445,7 +1448,7 @@ void drawBitmapTransparentByClipping(long srcHdc, long maskHdc, int srcX, int sr OS.DeleteObject(rgn); } -void drawBitmapMask(Image srcImage, long srcColor, long srcMask, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, int imgWidth, int imgHeight, boolean offscreen) { +void drawBitmapMask(long srcColor, long srcMask, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, int imgWidth, int imgHeight, boolean offscreen) { int srcColorY = srcY; if (srcColor == 0) { srcColor = srcMask; @@ -1497,11 +1500,11 @@ void drawBitmapMask(Image srcImage, long srcColor, long srcMask, int srcX, int s OS.DeleteDC(srcHdc); } -void drawBitmapTransparent(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, BITMAP bm, int imgWidth, int imgHeight) { +void drawBitmapTransparent(Image srcImage, long imageHandle, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, BITMAP bm, int imgWidth, int imgHeight) { /* Find the RGB values for the transparent pixel. */ boolean isDib = bm.bmBits != 0; - long hBitmap = Image.win32_getHandle(srcImage, getZoom()); + long hBitmap = imageHandle; long srcHdc = OS.CreateCompatibleDC(handle); long oldSrcBitmap = OS.SelectObject(srcHdc, hBitmap); byte[] originalColors = null; @@ -1546,7 +1549,7 @@ void drawBitmapTransparent(Image srcImage, int srcX, int srcY, int srcWidth, int bmiHeader.biBitCount = bm.bmBitsPixel; byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4]; OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof); - OS.GetDIBits(srcHdc, Image.win32_getHandle(srcImage, getZoom()), 0, 0, null, bmi, OS.DIB_RGB_COLORS); + OS.GetDIBits(srcHdc, imageHandle, 0, 0, null, bmi, OS.DIB_RGB_COLORS); int offset = BITMAPINFOHEADER.sizeof + 4 * srcImage.transparentPixel; transRed = bmi[offset + 2] & 0xFF; transGreen = bmi[offset + 1] & 0xFF; @@ -1619,13 +1622,13 @@ void drawBitmapTransparent(Image srcImage, int srcX, int srcY, int srcWidth, int OS.DeleteObject(maskBitmap); } OS.SelectObject(srcHdc, oldSrcBitmap); - if (hBitmap != Image.win32_getHandle(srcImage, getZoom())) OS.DeleteObject(hBitmap); + if (hBitmap != imageHandle) OS.DeleteObject(hBitmap); OS.DeleteDC(srcHdc); } -void drawBitmapColor(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) { +void drawBitmapColor(long imageHandle, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) { long srcHdc = OS.CreateCompatibleDC(handle); - long oldSrcBitmap = OS.SelectObject(srcHdc, Image.win32_getHandle(srcImage, getZoom())); + long oldSrcBitmap = OS.SelectObject(srcHdc, imageHandle); int dwRop = OS.GetROP2(handle) == OS.R2_XORPEN ? OS.SRCINVERT : OS.SRCCOPY; if (!simple && (srcWidth != destWidth || srcHeight != destHeight)) { int mode = OS.SetStretchBltMode(handle, OS.COLORONCOLOR);