From b0133c836beb68dff9bf1092fa509a8cab9e57e7 Mon Sep 17 00:00:00 2001 From: Andreas Koch Date: Wed, 2 Apr 2025 17:43:10 +0200 Subject: [PATCH] [win32] Handle all scaled font via SWTFontProvider This commit extends the SWTFontProvider and the SWTFontRegistry to receive scaled variants of a font where only the handle is available. Common use case for this is OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0) to receive the handle of the current font of a handle. As at this point the correct zoom the handle was created is not yet know, it is better to retrieve and manage those fonts via the SWTFontRegistry expecially when monitor specific scaling is used. When the passed font handle is not already managed via the SWTFontRegistry it will create the SWT Font as it was create previously. --- .../win32/org/eclipse/swt/graphics/GC.java | 8 ++++---- .../swt/internal/DefaultSWTFontRegistry.java | 5 +++++ .../org/eclipse/swt/internal/SWTFontProvider.java | 15 +++++++++++++++ .../org/eclipse/swt/internal/SWTFontRegistry.java | 12 ++++++++++++ .../swt/internal/ScalingSWTFontRegistry.java | 10 ++++++++++ .../win32/org/eclipse/swt/widgets/Composite.java | 3 ++- .../win32/org/eclipse/swt/widgets/Control.java | 10 +++++++--- 7 files changed, 55 insertions(+), 8 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 54b81968559..0fe325f075e 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 @@ -3898,14 +3898,14 @@ void init(Drawable drawable, GCData data, long hDC) { data.background = OS.GetBkColor(hDC); } data.state &= ~(NULL_BRUSH | NULL_PEN); + if (data.nativeZoom == 0) { + data.nativeZoom = extractZoom(hDC); + } Font font = data.font; if (font != null) { data.state &= ~FONT; } else { - data.font = Font.win32_new(device, OS.GetCurrentObject(hDC, OS.OBJ_FONT)); - } - if (data.nativeZoom == 0) { - data.nativeZoom = extractZoom(hDC); + data.font = SWTFontProvider.getFont(device, OS.GetCurrentObject(hDC, OS.OBJ_FONT), data.nativeZoom); } Image image = data.image; if (image != null) { diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/DefaultSWTFontRegistry.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/DefaultSWTFontRegistry.java index ba47b8ce771..89a56015346 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/DefaultSWTFontRegistry.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/DefaultSWTFontRegistry.java @@ -71,6 +71,11 @@ public Font getFont(FontData fontData, int zoom) { return font; } + @Override + public Font getFont(long fontHandle, int zoom) { + return Font.win32_new(device, fontHandle, zoom); + } + private Font registerFont(FontData fontData, Font font) { FontData clonedFontData = new FontData(fontData.toString()); fontsMap.put(clonedFontData, font); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/SWTFontProvider.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/SWTFontProvider.java index 1f4cae17f0e..9588982ed75 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/SWTFontProvider.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/SWTFontProvider.java @@ -61,6 +61,21 @@ public static Font getFont(Device device, FontData fontData, int zoom) { return getFontRegistry(device).getFont(fontData, zoom); } + /** + * Returns the font with the given fontHandle for the given device at the + * specified zoom. + * + * Note: This operation is not thread-safe. It must thus always be called + * from the same thread for the same device, such as the display's UI thread. + * + * @param device the device to retrieve the font for, must not be {@code null} + * @param fontHandle the handle to an existing font + * @param zoom the zoom for which the font shall be scaled + */ + public static Font getFont(Device device, long fontHandle, int zoom) { + return getFontRegistry(device).getFont(fontHandle, zoom); + } + /** * Disposes the font registry for the given device, if one exists. * diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/SWTFontRegistry.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/SWTFontRegistry.java index 02a19ee2a1d..f045453bc9a 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/SWTFontRegistry.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/SWTFontRegistry.java @@ -46,6 +46,18 @@ public interface SWTFontRegistry { */ Font getFont(FontData fontData, int zoom); + + /** + * Provides a font optimally suited for the specified zoom. If the handle is yet unknown to + * the registry, the font will not be managed by the font registry. Only Fonts created in the + * font registry are managed by it and should not be disposed of externally. + * + * @param fontHandle the handle to an existing font + * @param zoom zoom in % of the standard resolution to determine the appropriate font + * @return the font best suited for the specified zoom + */ + Font getFont(long fontHandle, int zoom); + /** * Disposes all fonts managed by the font registry. */ diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ScalingSWTFontRegistry.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ScalingSWTFontRegistry.java index 435a7ddb934..fa67ea09f3b 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ScalingSWTFontRegistry.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ScalingSWTFontRegistry.java @@ -44,6 +44,7 @@ private Font getScaledFont(int zoom) { private Font createAndCacheFont(int zoom) { Font newFont = createFont(zoom); + customFontHandlesKeyMap.put(newFont.handle, this); scaledFonts.put(zoom, newFont); return newFont; } @@ -112,6 +113,7 @@ protected void dispose() { private ScaledFontContainer systemFontContainer; private Map customFontsKeyMap = new HashMap<>(); + private Map customFontHandlesKeyMap = new HashMap<>(); private Device device; ScalingSWTFontRegistry(Device device) { @@ -137,6 +139,14 @@ public Font getFont(FontData fontData, int zoom) { return container.getScaledFont(zoom); } + @Override + public Font getFont(long fontHandle, int zoom) { + if (customFontHandlesKeyMap.containsKey(fontHandle)) { + return customFontHandlesKeyMap.get(fontHandle).getScaledFont(zoom); + } + return Font.win32_new(device, fontHandle, zoom); + } + @Override public void dispose() { customFontsKeyMap.values().forEach(ScaledFontContainer::dispose); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java index dad215d6cd6..1d727031dcc 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java @@ -1525,7 +1525,6 @@ LRESULT WM_PAINT (long wParam, long lParam) { Control control = findBackgroundControl (); if (control == null) control = this; data.background = control.getBackgroundPixel (); - data.font = Font.win32_new(display, OS.SendMessage (handle, OS.WM_GETFONT, 0, 0), getNativeZoom()); data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); if ((style & SWT.NO_BACKGROUND) != 0) { /* This code is intentionally commented because it may be slow to copy bits from the screen */ @@ -1536,6 +1535,8 @@ LRESULT WM_PAINT (long wParam, long lParam) { drawBackground (phdc [0], rect); } GC gc = createNewGC(phdc [0], data); + data.font = SWTFontProvider.getFont(display, OS.SendMessage (handle, OS.WM_GETFONT, 0, 0), data.nativeZoom); + Event event = new Event (); event.gc = gc; event.setBounds(DPIUtil.scaleDown(new Rectangle(ps.left, ps.top, width, height), getZoom())); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java index aa7e156e95b..c7617eeb70a 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java @@ -1315,7 +1315,7 @@ public Font getFont () { if (font != null) return font; long hFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); if (hFont == 0) hFont = defaultFont (); - return Font.win32_new (display, hFont, getNativeZoom()); + return SWTFontProvider.getFont(display, hFont, getNativeZoom()); } /** @@ -1753,14 +1753,18 @@ public long internal_new_GC (GCData data) { } } data.device = display; - data.nativeZoom = nativeZoom; + data.nativeZoom = getNativeZoom(); int foreground = getForegroundPixel (); if (foreground != OS.GetTextColor (hDC)) data.foreground = foreground; Control control = findBackgroundControl (); if (control == null) control = this; int background = control.getBackgroundPixel (); if (background != OS.GetBkColor (hDC)) data.background = background; - data.font = font != null ? font : Font.win32_new (display, OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0)); + if (font != null) { + data.font = font; + } else { + data.font = SWTFontProvider.getFont(display, OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0), data.nativeZoom); + } data.uiState = (int)OS.SendMessage (hwnd, OS.WM_QUERYUISTATE, 0, 0); } return hDC;