Skip to content

Commit 4fecda7

Browse files
akoch-yattaHeikoKlare
authored andcommitted
[win32] Refactor ScalingSWTFontRegistry to reduce complexity
This commit refactors ScalingSWTFontRegistry to simplify creation and caching of scaled variants of custom and system fonts. This is possible because the conversion of SWT font height in points to the OS font height in pixels no longer relies on the primary monitor zoom, but can directly calculated based on the target zoom a font will be used on now.
1 parent de48ec2 commit 4fecda7

File tree

1 file changed

+80
-117
lines changed

1 file changed

+80
-117
lines changed

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ScalingSWTFontRegistry.java

Lines changed: 80 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
package org.eclipse.swt.internal;
1515

1616
import java.util.*;
17-
import java.util.Map.*;
1817

1918
import org.eclipse.swt.graphics.*;
2019
import org.eclipse.swt.internal.win32.*;
@@ -28,154 +27,118 @@
2827
* The behavior can change any time in a future release.
2928
*/
3029
final class ScalingSWTFontRegistry implements SWTFontRegistry {
31-
private class ScaledFontContainer {
32-
// the first (unknown) font to be requested as scaled variant
33-
// usually it is scaled to the primary monitor zoom, but that is not guaranteed
34-
private Font baseFont;
35-
private Map<Integer, Font> scaledFonts = new HashMap<>();
36-
37-
ScaledFontContainer(Font baseFont, int fontZoom) {
38-
this.baseFont = baseFont;
39-
scaledFonts.put(fontZoom, baseFont);
40-
}
30+
private abstract class ScaledFontContainer {
31+
protected Map<Integer, Font> scaledFonts = new HashMap<>();
4132

42-
private Font getScaledFont(int targetZoom) {
43-
if (scaledFonts.containsKey(targetZoom)) {
44-
Font font = scaledFonts.get(targetZoom);
33+
private Font getScaledFont(int zoom) {
34+
if (scaledFonts.containsKey(zoom)) {
35+
Font font = scaledFonts.get(zoom);
4536
if (font.isDisposed()) {
46-
scaledFonts.remove(targetZoom);
47-
return null;
37+
scaledFonts.remove(zoom);
38+
return createAndCacheFont(zoom);
4839
}
4940
return font;
5041
}
51-
return null;
42+
return createAndCacheFont(zoom);
5243
}
5344

54-
private Font scaleFont(int zoom) {
55-
FontData fontData = baseFont.getFontData()[0];
56-
int baseZoom = computeZoom(fontData);
57-
fontData.data.lfHeight = Math.round(1.0f * fontData.data.lfHeight * zoom / baseZoom);
58-
Font scaledFont = Font.win32_new(device, fontData, zoom);
59-
addScaledFont(zoom, scaledFont);
60-
return scaledFont;
45+
private Font createAndCacheFont(int zoom) {
46+
Font newFont = createFont(zoom);
47+
scaledFonts.put(zoom, newFont);
48+
return newFont;
6149
}
6250

63-
private void addScaledFont(int targetZoom, Font scaledFont) {
64-
scaledFonts.put(targetZoom, scaledFont);
65-
}
51+
protected abstract Font createFont(int zoom);
52+
53+
protected abstract void dispose();
6654
}
6755

68-
private static FontData KEY_SYSTEM_FONTS = new FontData();
69-
private Map<Long, ScaledFontContainer> fontHandleMap = new HashMap<>();
70-
private Map<FontData, ScaledFontContainer> fontKeyMap = new HashMap<>();
71-
private Device device;
56+
private class ScaledCustomFontContainer extends ScaledFontContainer {
57+
private final FontData fontData;
7258

73-
ScalingSWTFontRegistry(Device device) {
74-
this.device = device;
75-
}
59+
ScaledCustomFontContainer(FontData fontData) {
60+
this.fontData = fontData;
61+
}
7662

77-
@Override
78-
public Font getSystemFont(int zoom) {
79-
ScaledFontContainer container = getOrCreateBaseSystemFontContainer(device);
63+
@Override
64+
protected Font createFont(int zoom) {
65+
return Font.win32_new(device, fontData, zoom);
66+
}
8067

81-
Font systemFont = container.getScaledFont(zoom);
82-
if (systemFont != null) {
83-
return systemFont;
68+
@Override
69+
protected void dispose() {
70+
for (Font font : scaledFonts.values()) {
71+
font.dispose();
72+
}
8473
}
85-
long systemFontHandle = createSystemFont(zoom);
86-
systemFont = Font.win32_new(device, systemFontHandle, zoom);
87-
container.addScaledFont(zoom, systemFont);
88-
return systemFont;
8974
}
9075

91-
private ScaledFontContainer getOrCreateBaseSystemFontContainer(Device device) {
92-
ScaledFontContainer systemFontContainer = fontKeyMap.get(KEY_SYSTEM_FONTS);
93-
if (systemFontContainer == null) {
94-
long hDC = device.internal_new_GC (null);
95-
int dpiX = OS.GetDeviceCaps (hDC, OS.LOGPIXELSX);
96-
device.internal_dispose_GC (hDC, null);
97-
int primaryZoom = DPIUtil.mapDPIToZoom(dpiX);
98-
long systemFontHandle = createSystemFont(primaryZoom);
99-
Font systemFont = Font.win32_new(device, systemFontHandle, primaryZoom);
100-
systemFontContainer = new ScaledFontContainer(systemFont, primaryZoom);
101-
fontHandleMap.put(systemFont.handle, systemFontContainer);
102-
fontKeyMap.put(KEY_SYSTEM_FONTS, systemFontContainer);
76+
private class ScaledSystemFontContainer extends ScaledFontContainer {
77+
@Override
78+
protected Font createFont(int zoom) {
79+
long newHandle = createSystemFontHandle(zoom);
80+
return Font.win32_new(device, newHandle, zoom);
81+
}
82+
83+
private long createSystemFontHandle(int zoom) {
84+
long hFont = 0;
85+
NONCLIENTMETRICS info = new NONCLIENTMETRICS();
86+
info.cbSize = NONCLIENTMETRICS.sizeof;
87+
if (fetchSystemParametersInfo(info, zoom)) {
88+
LOGFONT logFont = info.lfMessageFont;
89+
hFont = OS.CreateFontIndirect(logFont);
90+
}
91+
if (hFont == 0)
92+
hFont = OS.GetStockObject(OS.DEFAULT_GUI_FONT);
93+
if (hFont == 0)
94+
hFont = OS.GetStockObject(OS.SYSTEM_FONT);
95+
return hFont;
10396
}
104-
return systemFontContainer;
105-
}
10697

107-
private long createSystemFont(int targetZoom) {
108-
long hFont = 0;
109-
NONCLIENTMETRICS info = new NONCLIENTMETRICS();
110-
info.cbSize = NONCLIENTMETRICS.sizeof;
111-
if (fetchSystemParametersInfo(info, targetZoom)) {
112-
LOGFONT logFont = info.lfMessageFont;
113-
hFont = OS.CreateFontIndirect(logFont);
98+
private static boolean fetchSystemParametersInfo(NONCLIENTMETRICS info, int targetZoom) {
99+
if (OS.WIN32_BUILD >= OS.WIN32_BUILD_WIN10_1607) {
100+
return OS.SystemParametersInfoForDpi(OS.SPI_GETNONCLIENTMETRICS, NONCLIENTMETRICS.sizeof, info, 0,
101+
DPIUtil.mapZoomToDPI(targetZoom));
102+
} else {
103+
return OS.SystemParametersInfo(OS.SPI_GETNONCLIENTMETRICS, 0, info, 0);
104+
}
114105
}
115-
if (hFont == 0)
116-
hFont = OS.GetStockObject(OS.DEFAULT_GUI_FONT);
117-
if (hFont == 0)
118-
hFont = OS.GetStockObject(OS.SYSTEM_FONT);
119-
return hFont;
120-
}
121106

122-
private static boolean fetchSystemParametersInfo(NONCLIENTMETRICS info, int targetZoom) {
123-
if (OS.WIN32_BUILD >= OS.WIN32_BUILD_WIN10_1607) {
124-
return OS.SystemParametersInfoForDpi(OS.SPI_GETNONCLIENTMETRICS, NONCLIENTMETRICS.sizeof, info, 0,
125-
DPIUtil.mapZoomToDPI(targetZoom));
126-
} else {
127-
return OS.SystemParametersInfo(OS.SPI_GETNONCLIENTMETRICS, 0, info, 0);
107+
@Override
108+
protected void dispose() {
109+
// do not dispose the system fonts, they are not tied to the device of this registry
128110
}
129111
}
130112

113+
private ScaledFontContainer systemFontContainer;
114+
private Map<FontData, ScaledFontContainer> customFontsKeyMap = new HashMap<>();
115+
private Device device;
116+
117+
ScalingSWTFontRegistry(Device device) {
118+
this.device = device;
119+
systemFontContainer = new ScaledSystemFontContainer();
120+
}
121+
122+
@Override
123+
public Font getSystemFont(int zoom) {
124+
return systemFontContainer.getScaledFont(zoom);
125+
}
126+
131127
@Override
132128
public Font getFont(FontData fontData, int zoom) {
133129
ScaledFontContainer container;
134-
if (fontKeyMap.containsKey(fontData)) {
135-
container = fontKeyMap.get(fontData);
130+
if (customFontsKeyMap.containsKey(fontData)) {
131+
container = customFontsKeyMap.get(fontData);
136132
} else {
137-
int calculatedZoom = computeZoom(fontData);
138-
Font newFont = Font.win32_new(device, fontData, calculatedZoom);
139-
container = new ScaledFontContainer(newFont, calculatedZoom);
140-
fontHandleMap.put(newFont.handle, container);
141-
fontKeyMap.put(fontData, container);
133+
container = new ScaledCustomFontContainer(fontData);
134+
customFontsKeyMap.put(fontData, container);
142135
}
143-
return getOrCreateFont(container, zoom);
136+
return container.getScaledFont(zoom);
144137
}
145138

146139
@Override
147140
public void dispose() {
148-
for (Entry<FontData, ScaledFontContainer> fontContainerEntry : fontKeyMap.entrySet()) {
149-
if (KEY_SYSTEM_FONTS.equals(fontContainerEntry.getKey())) {
150-
// do not dispose the system fonts here, they are not tied to the device of this registry
151-
continue;
152-
}
153-
ScaledFontContainer scaledFontContainer = fontContainerEntry.getValue();
154-
for (Font font : scaledFontContainer.scaledFonts.values()) {
155-
font.dispose();
156-
}
157-
}
158-
fontKeyMap.clear();
159-
}
160-
161-
private Font getOrCreateFont(ScaledFontContainer container, int zoom) {
162-
Font scaledFont = container.getScaledFont(zoom);
163-
if (scaledFont == null) {
164-
scaledFont = container.scaleFont(zoom);
165-
fontHandleMap.put(scaledFont.handle, container);
166-
fontKeyMap.put(scaledFont.getFontData()[0], container);
167-
}
168-
return scaledFont;
169-
}
170-
171-
private int computeZoom(FontData fontData) {
172-
int pixelHeight = fontData.data.lfHeight;
173-
float currentPointHeight = fontData.height;
174-
if (pixelHeight == 0 || Math.abs(currentPointHeight) < 0.001) {
175-
// if there is no font yet available, we use a defined zoom
176-
return 100;
177-
}
178-
float pointHeightOn100 = -(pixelHeight / 96f * 72f);
179-
return Math.round(100.0f * pointHeightOn100 / currentPointHeight);
141+
customFontsKeyMap.values().forEach(ScaledFontContainer::dispose);
142+
customFontsKeyMap.clear();
180143
}
181144
}

0 commit comments

Comments
 (0)