Using custom registered font, `setFont()` is not working, but `getFont*()` overridden makes it work
Hello, thank you for your work on this great library!
Description
Using setFont() on RSyntaxTextArea is not working for registered font (or for any unclear root cause), the custom font is ignored and the default font is used instead.
Issue is fixed when we override the methods getFont*() (see below).
Steps to Reproduce
- First load a font :
var graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
InputStream fontStream = new BufferedInputStream(
UiUtil.class.getClassLoader().getResourceAsStream("swing/font/UbuntuMono-R-ctrlchar.ttf")
);
var ubuntuFont = Font.createFont(Font.TRUETYPE_FONT, fontStream);
graphicsEnvironment.registerFont(ubuntuFont);
- The next code displays the default font instead of the custom font (see Actual behavior):
RSyntaxTextArea textArea = new RSyntaxTextArea("text");
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL);
textArea.setFont(new Font("Ubuntu Mono", Font.PLAIN, 12));
- The next code overrides the methods
getFont*()and displays the custom font properly (see Expected behavior):
RSyntaxTextArea textArea = new RSyntaxTextArea("text") {
@Override
public Font getFont() {
return new Font("Ubuntu Mono", Font.PLAIN, 12);
}
@Override
public Font getFontForToken(Token token) {
return new Font("Ubuntu Mono", Font.PLAIN, 12);
}
@Override
public Font getFontForTokenType(int type) {
return new Font("Ubuntu Mono", Font.PLAIN, 12);
}
};
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL);
Expected behavior Correct custom font is displayed when overridden :
Actual behavior
Unexpected default font is displayed using setFont() :
Java version Same issue and fix tested on jdk11, jdk17, jdk23.
Hmm, I can't reproduce this, at least on Windows 10 + Java 17.
To eliminate it being a property of the specific font somehow - I tested with this one.
SSCCE:
package org.fife.ui.rsyntaxtextarea.demo;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rtextarea.RTextScrollPane;
import javax.swing.*;
import java.awt.*;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
public final class RSyntaxTextAreaDemoApp2 extends JFrame {
private RSyntaxTextAreaDemoApp2() {
RSyntaxTextArea textArea = new RSyntaxTextArea(25, 60);
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL);
try {
GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
InputStream fontStream = new BufferedInputStream(
Files.newInputStream(Paths.get("D:/temp/UbuntuMono-R.ttf"))
);
Font newFont = Font.createFont(Font.TRUETYPE_FONT, fontStream);
graphicsEnvironment.registerFont(newFont);
textArea.setFont(new Font("Ubuntu Mono", Font.PLAIN, 14));//newFont);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
textArea.setText("Using font: " + textArea.getFont().getFamily() + "\n\n" +
"http://localhost:8080 abcdefghijklmnopqrstuvwxyz");
RTextScrollPane scrollPane = new RTextScrollPane(textArea);
setContentPane(scrollPane);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setTitle("RSyntaxTextArea Demo Application");
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace(); // Never happens
}
Toolkit.getDefaultToolkit().setDynamicLayout(true);
new RSyntaxTextAreaDemoApp2().setVisible(true);
});
}
}
Produces this output (the font doesn't look great, but the individual glyphs look like those in your "expected screenshot?):
| Without loading the font | With loading the font |
|---|---|
@ron190 can you provide the OS, exact font TTF file, and any other info that might help narrow things down?
Based on your SSCCE, I manage to reproduce the font reset behavior on 2 different ways :
- either I set a theme after having set the font
- or I update the UI after having set the font
I'm facing these behaviors as my app can switch theme at runtime when font is already set 😅
Way 1: When font is set, setting a theme is resetting to default font
textArea.setFont(new Font("Ubuntu Mono", Font.PLAIN, 14));//newFont); 👈
Theme theme = Theme.load(
RSyntaxTextAreaDemoApp2.class.getResourceAsStream("/org/fife/ui/rsyntaxtextarea/themes/dark.xml")
);
theme.apply(textArea);
Setting theme before the font displays expected font :
Theme theme = Theme.load(
RSyntaxTextAreaDemoApp2.class.getResourceAsStream("/org/fife/ui/rsyntaxtextarea/themes/dark.xml")
);
theme.apply(textArea);
textArea.setFont(new Font("Ubuntu Mono", Font.PLAIN, 14));//newFont); 👈
Way 2: When font is set, updating the UI is resetting to default font
Issue displays here :
new RSyntaxTextAreaDemoApp2().setVisible(true); 👈
for (Window w: Window.getWindows()) {
SwingUtilities.updateComponentTreeUI(w);
}
No issue :
for (Window w: Window.getWindows()) {
SwingUtilities.updateComponentTreeUI(w);
}
new RSyntaxTextAreaDemoApp2().setVisible(true); 👈
Gotcha! Reproducible now.
It may not have been the best decision, or the most intuitive, but applying a new theme always resets the font to the editor default, unless you use the load() overload that configure the Theme font:
Theme theme = Theme.load(in, textArea.getFont());
theme.apply(textArea);
That should solve your "Way 1."
I can't reproduce with your Way 2 though, and it shouln't change when updating the UI, unless you use a FontUIResource instead of a Font. Can you confirm whether you're doing that?
SSCCE with updateComponentTreeUI:
package org.fife.ui.rsyntaxtextarea.demo;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rsyntaxtextarea.Theme;
import org.fife.ui.rtextarea.RTextScrollPane;
import javax.swing.*;
import java.awt.*;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
public final class RSyntaxTextAreaDemoApp2 extends JFrame {
private RSyntaxTextAreaDemoApp2() {
RSyntaxTextArea textArea = new RSyntaxTextArea(25, 60);
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL);
try {
GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
InputStream fontStream = new BufferedInputStream(
Files.newInputStream(Paths.get("/Users/robert/Downloads/UbuntuMono-R.ttf"))
);
Font newFont = Font.createFont(Font.TRUETYPE_FONT, fontStream);
graphicsEnvironment.registerFont(newFont);
textArea.setFont(new Font("Ubuntu Mono", Font.PLAIN, 14));//newFont);
// Theme theme = Theme.load(
// RSyntaxTextAreaDemoApp2.class.getResourceAsStream("/org/fife/ui/rsyntaxtextarea/themes/dark.xml")
// );
// theme.apply(textArea);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
textArea.setText("Using font: " + textArea.getFont().getFamily() + "\n\n" +
"http://localhost:8080 abcdefghijklmnopqrstuvwxyz");
RTextScrollPane scrollPane = new RTextScrollPane(textArea);
setContentPane(scrollPane);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setTitle("RSyntaxTextArea Demo Application");
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace(); // Never happens
}
Toolkit.getDefaultToolkit().setDynamicLayout(true);
new RSyntaxTextAreaDemoApp2().setVisible(true);
for (Window w: Window.getWindows()) {
SwingUtilities.updateComponentTreeUI(w);
}
});
}
}
Links just for reference to the legacy code, as I don't know if I use FontUIResource or not, I tried something similar to :
- loading font and adding with
UIManager.put() - removing my
getFont*()override - restoring
setFont()on the textarea - using the other signature
Theme.load(InputStream, Font)
But it still not loads the custom font, though I suppose it reveals there's a 3rd way that's not loading the custom font :
Way 3: When loading custom font by UIManager.put(), default font shows
SSCCE with UIManager.put() working on JTextArea, but not working on RSyntaxTextArea
package com.jsql.view.swing;
import com.jsql.view.swing.util.UiUtil;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rsyntaxtextarea.Theme;
import org.fife.ui.rtextarea.RTextScrollPane;
import javax.swing.*;
import java.awt.*;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Objects;
public final class RSyntaxTextAreaDemoApp2 extends JFrame {
private RSyntaxTextAreaDemoApp2() {
RSyntaxTextArea textArea = new RSyntaxTextArea(25, 60);
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL);
try {
GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
InputStream fontStream = new BufferedInputStream(
// Files.newInputStream(Paths.get("swing/font/UbuntuMono-R-ctrlchar.ttf"))
Objects.requireNonNull(UiUtil.class.getClassLoader().getResourceAsStream("swing/font/UbuntuMono-R-ctrlchar.ttf"))
);
Font newFont = Font.createFont(Font.TRUETYPE_FONT, fontStream);
graphicsEnvironment.registerFont(newFont);
// textArea.setFont(new Font("Ubuntu Mono", Font.PLAIN, 14));//newFont);
UIManager.put("TextArea.font", newFont.deriveFont(24f));
// Theme theme = Theme.load(
// RSyntaxTextAreaDemoApp2.class.getResourceAsStream("/org/fife/ui/rsyntaxtextarea/themes/dark.xml")
// );
// theme.apply(textArea);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
textArea.setText("Using font: " + textArea.getFont().getFamily() + "\n\n" +
"http://localhost:8080 abcdefghijklmnopqrstuvwxyz");
RTextScrollPane scrollPane = new RTextScrollPane(textArea);
// setContentPane(scrollPane);
setContentPane(new JScrollPane(new JTextArea("azeaz 0123456789 0000")));
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setTitle("RSyntaxTextArea Demo Application");
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace(); // Never happens
}
Toolkit.getDefaultToolkit().setDynamicLayout(true);
new RSyntaxTextAreaDemoApp2().setVisible(true);
// for (Window w: Window.getWindows()) {
// SwingUtilities.updateComponentTreeUI(w);
// }
});
}
}
Also for reference, the SSCCEs for the 2 other ways:
Way 1: When font is set, setting a theme is resetting to default font
package com.jsql.view.swing;
import com.jsql.view.swing.util.UiUtil;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rsyntaxtextarea.Theme;
import org.fife.ui.rtextarea.RTextScrollPane;
import javax.swing.*;
import java.awt.*;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Objects;
public final class RSyntaxTextAreaDemoApp2 extends JFrame {
private RSyntaxTextAreaDemoApp2() {
RSyntaxTextArea textArea = new RSyntaxTextArea(25, 60);
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL);
try {
GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
InputStream fontStream = new BufferedInputStream(
// Files.newInputStream(Paths.get("swing/font/UbuntuMono-R-ctrlchar.ttf"))
Objects.requireNonNull(UiUtil.class.getClassLoader().getResourceAsStream("swing/font/UbuntuMono-R-ctrlchar.ttf"))
);
Font newFont = Font.createFont(Font.TRUETYPE_FONT, fontStream);
graphicsEnvironment.registerFont(newFont);
textArea.setFont(new Font("Ubuntu Mono", Font.PLAIN, 14));//newFont);
// UIManager.put("TextArea.font", newFont.deriveFont(24f));
Theme theme = Theme.load(
RSyntaxTextAreaDemoApp2.class.getResourceAsStream("/org/fife/ui/rsyntaxtextarea/themes/dark.xml")
);
theme.apply(textArea);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
textArea.setText("Using font: " + textArea.getFont().getFamily() + "\n\n" +
"http://localhost:8080 abcdefghijklmnopqrstuvwxyz");
RTextScrollPane scrollPane = new RTextScrollPane(textArea);
setContentPane(scrollPane);
// setContentPane(new JScrollPane(new JTextArea("azeaz 0123456789 0000")));
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setTitle("RSyntaxTextArea Demo Application");
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace(); // Never happens
}
Toolkit.getDefaultToolkit().setDynamicLayout(true);
new RSyntaxTextAreaDemoApp2().setVisible(true);
// for (Window w: Window.getWindows()) {
// SwingUtilities.updateComponentTreeUI(w);
// }
});
}
}
Way 2: When font is set, updating the UI is resetting to default font
package com.jsql.view.swing;
import com.jsql.view.swing.util.UiUtil;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rsyntaxtextarea.Theme;
import org.fife.ui.rtextarea.RTextScrollPane;
import javax.swing.*;
import java.awt.*;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Objects;
public final class RSyntaxTextAreaDemoApp2 extends JFrame {
private RSyntaxTextAreaDemoApp2() {
RSyntaxTextArea textArea = new RSyntaxTextArea(25, 60);
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL);
try {
GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
InputStream fontStream = new BufferedInputStream(
// Files.newInputStream(Paths.get("swing/font/UbuntuMono-R-ctrlchar.ttf"))
Objects.requireNonNull(UiUtil.class.getClassLoader().getResourceAsStream("swing/font/UbuntuMono-R-ctrlchar.ttf"))
);
Font newFont = Font.createFont(Font.TRUETYPE_FONT, fontStream);
graphicsEnvironment.registerFont(newFont);
textArea.setFont(new Font("Ubuntu Mono", Font.PLAIN, 14));//newFont);
// UIManager.put("TextArea.font", newFont.deriveFont(24f));
// Theme theme = Theme.load(
// RSyntaxTextAreaDemoApp2.class.getResourceAsStream("/org/fife/ui/rsyntaxtextarea/themes/dark.xml")
// );
// theme.apply(textArea);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
textArea.setText("Using font: " + textArea.getFont().getFamily() + "\n\n" +
"http://localhost:8080 abcdefghijklmnopqrstuvwxyz");
RTextScrollPane scrollPane = new RTextScrollPane(textArea);
setContentPane(scrollPane);
// setContentPane(new JScrollPane(new JTextArea("azeaz 0123456789 0000")));
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setTitle("RSyntaxTextArea Demo Application");
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace(); // Never happens
}
Toolkit.getDefaultToolkit().setDynamicLayout(true);
new RSyntaxTextAreaDemoApp2().setVisible(true);
for (Window w: Window.getWindows()) {
SwingUtilities.updateComponentTreeUI(w);
}
});
}
}