Skip to content

Commit 7c2cc38

Browse files
akoch-yattaHeikoKlare
authored andcommitted
[win32] Cache font height to prevent inconsistency
This commit adapts a limitation of handling fonts in the win32 implementation. When a font is initialized with FontData the height in points of it and the desired target zoom will be used to calculate the font height in pixels. When the FontData of an existing font is retrieved the Logfont data from the OS together with the font zoom are used to recalculate the original font height. As the conversion to pixels involved rounding, the reversed calculation will result in a different value than was used on creation time. With monitor-specific scaling a font for a different zoom will be calculated on the basis of the FontData of an existing base font. This can lead to font heights in pixels that differ from the "correct" value. To solve this limitation each font stores its original font height in points to recreate the it when Font::getFontData is called.
1 parent d42bca6 commit 7c2cc38

File tree

2 files changed

+31
-16
lines changed

2 files changed

+31
-16
lines changed

bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/internal/ScalingSWTFontRegistryTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public void fontsAreCached() {
6767

6868
@Test
6969
public void fontsAreScaled() {
70-
FontData fontData = new FontData(TEST_FONT, 10, SWT.NORMAL);
70+
FontData fontData = new FontData(TEST_FONT, 9, SWT.NORMAL);
7171
FontData font100 = fontRegistry.getFont(fontData, 100).getFontData()[0];
7272
FontData font200 = fontRegistry.getFont(fontData, 200).getFontData()[0];
7373
assertEquals("Point height must be equal for all zoom factors", font100.getHeight(), font200.getHeight());

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Font.java

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,27 @@ public final class Font extends Resource {
5555
* (Warning: This field is platform dependent)
5656
*/
5757
int zoom;
58+
59+
/**
60+
* Font height in points. As the conversion to pixel height involves rounding the fontHeight must
61+
* be cached.
62+
*/
63+
private final float fontHeight;
64+
5865
/**
5966
* Prevents uninitialized instances from being created outside the package.
6067
*/
6168
Font(Device device) {
6269
super(device);
6370
this.zoom = extractZoom(this.device);
71+
this.fontHeight = 0;
72+
}
73+
74+
private Font(Device device, long handle, int zoom) {
75+
super(device);
76+
this.handle = handle;
77+
this.zoom = zoom;
78+
this.fontHeight = device.computePoints(fetchLogFontData(), handle, zoom);
6479
}
6580

6681
/**
@@ -87,13 +102,15 @@ public Font(Device device, FontData fd) {
87102
super(device);
88103
this.zoom = extractZoom(this.device);
89104
init(fd);
105+
this.fontHeight = fd.height;
90106
init();
91107
}
92108

93109
private Font(Device device, FontData fd, int zoom) {
94110
super(device);
95111
this.zoom = zoom;
96112
init(fd);
113+
this.fontHeight = fd.height;
97114
init();
98115
}
99116

@@ -130,7 +147,9 @@ public Font(Device device, FontData[] fds) {
130147
if (fd == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
131148
}
132149
this.zoom = extractZoom(this.device);
150+
FontData fd = fds[0];
133151
init(fds[0]);
152+
this.fontHeight = fd.height;
134153
init();
135154
}
136155

@@ -163,6 +182,7 @@ public Font(Device device, String name, int height, int style) {
163182
if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
164183
this.zoom = extractZoom(this.device);
165184
init(new FontData (name, height, style));
185+
this.fontHeight = height;
166186
init();
167187
}
168188

@@ -171,6 +191,7 @@ public Font(Device device, String name, int height, int style) {
171191
if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
172192
this.zoom = extractZoom(this.device);
173193
init(new FontData (name, height, style));
194+
this.fontHeight = height;
174195
init();
175196
}
176197
@Override
@@ -211,10 +232,14 @@ public boolean equals(Object object) {
211232
*/
212233
public FontData[] getFontData() {
213234
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
235+
LOGFONT logFont = fetchLogFontData();
236+
return new FontData[] {FontData.win32_new(logFont, fontHeight)};
237+
}
238+
239+
private LOGFONT fetchLogFontData() {
214240
LOGFONT logFont = new LOGFONT ();
215241
OS.GetObject(handle, LOGFONT.sizeof, logFont);
216-
float heightInPoints = device.computePoints(logFont, handle, zoom);
217-
return new FontData[] {FontData.win32_new(logFont, heightInPoints)};
242+
return logFont;
218243
}
219244

220245
/**
@@ -293,16 +318,8 @@ private static int extractZoom(Device device) {
293318
* @noreference This method is not intended to be referenced by clients.
294319
*/
295320
public static Font win32_new(Device device, long handle) {
296-
Font font = new Font(device);
297-
font.zoom = extractZoom(font.device);
298-
font.handle = handle;
299-
/*
300-
* When created this way, Font doesn't own its .handle, and
301-
* for this reason it can't be disposed. Tell leak detector
302-
* to just ignore it.
303-
*/
304-
font.ignoreNonDisposed();
305-
return font;
321+
int zoom = extractZoom(device);
322+
return win32_new(device, handle, zoom);
306323
}
307324

308325
/**
@@ -324,9 +341,7 @@ public static Font win32_new(Device device, long handle) {
324341
* @since 3.126
325342
*/
326343
public static Font win32_new(Device device, long handle, int zoom) {
327-
Font font = new Font(device);
328-
font.zoom = zoom;
329-
font.handle = handle;
344+
Font font = new Font(device, handle, zoom);
330345
/*
331346
* When created this way, Font doesn't own its .handle, and
332347
* for this reason it can't be disposed. Tell leak detector

0 commit comments

Comments
 (0)