Skip to content

Commit 6975bad

Browse files
committed
Dispose bold/italic fonts in FontRegistry upon display disposal
The FontRegistry implementation uses hooks to dispose registered fonts upon disposal of the display they have been created for. This implementation does, however, only cover the base fonts but not the bold/italic versions of them. In case only a bold/italic font of a record is created on a separate display, no dispose hook for that display will be created, such that those fonts will not be disposed when the display becomes disposed. In consequence, fonts for non-disposed devices may be returned by the registry. This change improves the FontRegistry implementation to create a display dispose hook also upon creation of a bold/italic font.
1 parent e6d3cbf commit 6975bad

2 files changed

Lines changed: 44 additions & 9 deletions

File tree

bundles/org.eclipse.jface/src/org/eclipse/jface/resource/FontRegistry.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ public Font getBoldFont() {
121121
}
122122

123123
FontData[] boldData = getModifiedFontData(SWT.BOLD);
124-
boldFont = new Font(Display.getCurrent(), boldData);
124+
Display display = getDisplayAndHookForDisposal();
125+
boldFont = new Font(display, boldData);
125126
return boldFont;
126127
}
127128

@@ -157,7 +158,8 @@ public Font getItalicFont() {
157158
}
158159

159160
FontData[] italicData = getModifiedFontData(SWT.ITALIC);
160-
italicFont = new Font(Display.getCurrent(), italicData);
161+
Display display = getDisplayAndHookForDisposal();
162+
italicFont = new Font(display, italicData);
161163
return italicFont;
162164
}
163165

@@ -489,13 +491,10 @@ else if (fonts.length == 0) {
489491
* @return FontRecord for the new Font or <code>null</code>.
490492
*/
491493
private FontRecord createFont(String symbolicName, FontData[] fonts) {
492-
Display display = Display.getCurrent();
494+
Display display = getDisplayAndHookForDisposal();
493495
if (display == null) {
494496
return null;
495497
}
496-
if (cleanOnDisplayDisposal && !displayDisposeHooked.contains(display)) {
497-
hookDisplayDispose(display);
498-
}
499498

500499
FontData[] validData = filterData(fonts, display);
501500
if (validData.length == 0) {
@@ -509,6 +508,17 @@ private FontRecord createFont(String symbolicName, FontData[] fonts) {
509508
return new FontRecord(newFont, validData);
510509
}
511510

511+
private Display getDisplayAndHookForDisposal() {
512+
Display display = Display.getCurrent();
513+
if (display == null) {
514+
return null;
515+
}
516+
if (cleanOnDisplayDisposal && !displayDisposeHooked.contains(display)) {
517+
hookDisplayDispose(display);
518+
}
519+
return display;
520+
}
521+
512522
/**
513523
* Calculates the default font and returns the result.
514524
* This method creates a font that must be disposed.

tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/resources/FontRegistryTest.java

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.time.Duration;
2424
import java.time.Instant;
2525
import java.util.concurrent.atomic.AtomicReference;
26+
import java.util.function.Supplier;
2627

2728
import org.eclipse.core.runtime.Platform.OS;
2829
import org.eclipse.jface.resource.FontRegistry;
@@ -58,10 +59,34 @@ public void multipleDisplayDispose() {
5859
assumeTrue(OS.isWindows(), "multiple Display instance only allowed on Windows");
5960

6061
FontRegistry fontRegistry = new FontRegistry();
62+
testMultipleDisplayDispose(fontRegistry::defaultFont);
63+
}
64+
65+
@Test
66+
public void multipleDisplayDispose_boldFont() {
67+
assumeTrue(OS.isWindows(), "multiple Display instance only allowed on Windows");
68+
69+
FontRegistry fontRegistry = new FontRegistry();
70+
fontRegistry.get(JFaceResources.DEFAULT_FONT);
71+
testMultipleDisplayDispose(() -> fontRegistry.getBold(JFaceResources.DEFAULT_FONT));
72+
}
73+
74+
@Test
75+
public void multipleDisplay_italicFont() {
76+
assumeTrue(OS.isWindows(), "multiple Display instance only allowed on Windows");
77+
78+
FontRegistry fontRegistry = new FontRegistry();
79+
fontRegistry.get(JFaceResources.DEFAULT_FONT);
80+
testMultipleDisplayDispose(() -> fontRegistry.getItalic(JFaceResources.DEFAULT_FONT));
81+
}
82+
83+
private static void testMultipleDisplayDispose(Supplier<Font> fontSupplier) {
84+
assumeTrue(OS.isWindows(), "multiple Display instance only allowed on Windows");
85+
6186
Display secondDisplay = initializeDisplayInSeparateThread();
62-
Font fontOnSecondDisplay = secondDisplay.syncCall(fontRegistry::defaultFont);
87+
Font fontOnSecondDisplay = secondDisplay.syncCall(fontSupplier::get);
6388

64-
Font fontOnThisDisplayBeforeSecondDisplayDispose = fontRegistry.defaultFont();
89+
Font fontOnThisDisplayBeforeSecondDisplayDispose = fontSupplier.get();
6590
Device displayOfFontOnSecondDisplay = fontOnSecondDisplay.getDevice();
6691
// font registry returns same font for every display
6792
assertEquals(secondDisplay, displayOfFontOnSecondDisplay);
@@ -70,7 +95,7 @@ public void multipleDisplayDispose() {
7095
// after disposing font's display, registry should reinitialize the font
7196
secondDisplay.syncExec(secondDisplay::dispose);
7297
assertTrue(fontOnSecondDisplay.isDisposed());
73-
Font fontOnThisDisplayAfterSecondDisplayDispose = fontRegistry.defaultFont();
98+
Font fontOnThisDisplayAfterSecondDisplayDispose = fontSupplier.get();
7499
assertNotEquals(fontOnThisDisplayAfterSecondDisplayDispose, fontOnSecondDisplay);
75100
}
76101

0 commit comments

Comments
 (0)