diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java index 2cde4900ad..ba65241334 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java @@ -29,6 +29,7 @@ import com.google.common.collect.ComparisonChain; import com.google.common.collect.ImmutableMap; import java.awt.Color; import java.awt.Dimension; +import java.awt.Font; import java.awt.Point; import java.awt.Rectangle; import java.io.File; @@ -61,6 +62,7 @@ import net.runelite.client.RuneLite; import net.runelite.client.account.AccountSession; import net.runelite.client.eventbus.EventBus; import net.runelite.client.util.ColorUtil; +import net.runelite.client.ui.FontManager; import net.runelite.http.api.config.ConfigClient; import net.runelite.http.api.config.ConfigEntry; import net.runelite.http.api.config.Configuration; @@ -512,6 +514,10 @@ public class ConfigManager { return Enum.valueOf((Class) type, str); } + if (type == Font.class) + { + return FontManager.getFontOrDefault(FontManager.lookupFont(str)); + } if (type == Instant.class) { return Instant.parse(str); @@ -540,6 +546,10 @@ public class ConfigManager { return ((Enum) object).name(); } + if (object instanceof Font) + { + return FontManager.getFontName((Font)object); + } if (object instanceof Dimension) { Dimension d = (Dimension) object; diff --git a/runelite-client/src/main/java/net/runelite/client/config/FontType.java b/runelite-client/src/main/java/net/runelite/client/config/FontType.java index 8ed57bd302..31809d287c 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/FontType.java +++ b/runelite-client/src/main/java/net/runelite/client/config/FontType.java @@ -26,20 +26,16 @@ package net.runelite.client.config; import lombok.RequiredArgsConstructor; import lombok.Getter; -import net.runelite.client.ui.FontManager; - -import java.awt.Font; @Getter @RequiredArgsConstructor public enum FontType { - REGULAR("Regular", FontManager.getRunescapeFont()), - BOLD("Bold", FontManager.getRunescapeBoldFont()), - SMALL("Small", FontManager.getRunescapeSmallFont()); + REGULAR("Regular"), + BOLD("Bold"), + SMALL("Small"); private final String name; - private final Font font; @Override public String toString() diff --git a/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java b/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java index 546f7e77bc..5566974afb 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java @@ -25,7 +25,9 @@ package net.runelite.client.config; import java.awt.Dimension; +import java.awt.Font; import net.runelite.api.Constants; +import net.runelite.client.ui.FontManager; @ConfigGroup("runelite") public interface RuneLiteConfig extends Config @@ -196,6 +198,17 @@ public interface RuneLiteConfig extends Config return false; } + @ConfigItem( + keyName = "clientFont", + name = "Font", + description = "Configure what font is used for the client and runelite added overlays", + position = 29 + ) + default Font clientFont() + { + return FontManager.getRunescapeFont(); + } + @ConfigItem( keyName = "fontType", name = "Dynamic Overlay Font", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java index b71d5e8b0e..9edbf71bf3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java @@ -30,6 +30,7 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; +import java.awt.Font; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.ItemEvent; @@ -84,6 +85,7 @@ import net.runelite.client.plugins.PluginInstantiationException; import net.runelite.client.plugins.PluginManager; import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.DynamicGridLayout; +import net.runelite.client.ui.FontManager; import net.runelite.client.ui.PluginPanel; import net.runelite.client.ui.components.ComboBoxListRenderer; import net.runelite.client.ui.components.IconButton; @@ -529,6 +531,37 @@ public class ConfigPanel extends PluginPanel item.add(button, BorderLayout.EAST); } + if (cid.getType() == Font.class) + { + JComboBox box = new JComboBox(FontManager.getAvailableFontNames()); + box.setPreferredSize(new Dimension(150, 25)); + box.setRenderer(new ComboBoxListRenderer()); + box.setForeground(Color.WHITE); + box.setFocusable(false); + String currentlyConfigured = configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()); + if (FontManager.lookupFont(currentlyConfigured) != null) + { + box.setSelectedItem(currentlyConfigured); + box.setToolTipText(currentlyConfigured); + } + else + { + log.debug("Selected font wasn't found on this system, resetting font back to runescape small"); + configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), FontManager.getRunescapeSmallFont()); + } + box.addItemListener(e -> + { + if (e.getStateChange() == ItemEvent.SELECTED && box.getSelectedItem() != null) + { + final Font selected = FontManager.lookupFont(box.getSelectedItem().toString()); + configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), selected); + box.setToolTipText(box.getSelectedItem().toString()); + } + }); + item.add(box, BorderLayout.EAST); + } + + mainPanel.add(item); } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java index 59ce146601..ced93fa930 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java @@ -302,7 +302,7 @@ public class ClientUI SwingUtil.setTheme(new SubstanceRuneLiteLookAndFeel()); // Use custom UI font - SwingUtil.setFont(FontManager.getRunescapeFont()); + SwingUtil.setFont(FontManager.getFontOrDefault(config.clientFont())); // Create main window frame = new ContainableFrame(); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java b/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java index b6fdac5172..3addfb26f9 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java @@ -24,11 +24,16 @@ */ package net.runelite.client.ui; -import javax.swing.text.StyleContext; +import com.google.common.collect.ImmutableBiMap; +import java.awt.Canvas; +import java.util.Arrays; +import java.util.Comparator; +import java.util.LinkedHashMap; import java.awt.Font; import java.awt.FontFormatException; import java.awt.GraphicsEnvironment; import java.io.IOException; +import net.runelite.client.config.FontType; public class FontManager { @@ -36,37 +41,45 @@ public class FontManager private static final Font runescapeSmallFont; private static final Font runescapeBoldFont; + private static final ImmutableBiMap fontMap; + static { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); try { - Font font = Font.createFont(Font.TRUETYPE_FONT, + runescapeFont = Font.createFont(Font.TRUETYPE_FONT, FontManager.class.getResourceAsStream("runescape.ttf")) .deriveFont(Font.PLAIN, 16); - ge.registerFont(font); - runescapeFont = StyleContext.getDefaultStyleContext() - .getFont(font.getName(), Font.PLAIN, 16); - ge.registerFont(runescapeFont); - - Font smallFont = Font.createFont(Font.TRUETYPE_FONT, + runescapeSmallFont = Font.createFont(Font.TRUETYPE_FONT, FontManager.class.getResourceAsStream("runescape_small.ttf")) .deriveFont(Font.PLAIN, 16); - ge.registerFont(smallFont); - runescapeSmallFont = StyleContext.getDefaultStyleContext() - .getFont(smallFont.getName(), Font.PLAIN, 16); + runescapeBoldFont = Font.createFont(Font.TRUETYPE_FONT, + FontManager.class.getResourceAsStream("runescape_bold.ttf")) + .deriveFont(Font.PLAIN, 16); + + final LinkedHashMap _fontMap = new LinkedHashMap<>(); + _fontMap.put("Runescape small", runescapeSmallFont); + _fontMap.put("Runescape default", runescapeFont); + _fontMap.put("Runescape bold", runescapeBoldFont); + + // Get all available fonts on the system + Font[] availableFonts = ge.getAllFonts(); + // build bidirectional map + Arrays.stream(availableFonts).sorted(Comparator.comparing(Font::getFontName)).forEach(f -> + { + if (!_fontMap.containsKey(f.getFontName())) + { + _fontMap.put(f.getFontName(), f); + } + }); + fontMap = ImmutableBiMap.copyOf(_fontMap); + + ge.registerFont(runescapeFont); ge.registerFont(runescapeSmallFont); - - Font boldFont = Font.createFont(Font.TRUETYPE_FONT, - FontManager.class.getResourceAsStream("runescape_bold.ttf")) - .deriveFont(Font.PLAIN, 16); - ge.registerFont(boldFont); - - runescapeBoldFont = StyleContext.getDefaultStyleContext() - .getFont(boldFont.getName(), Font.PLAIN, 16); ge.registerFont(runescapeBoldFont); } catch (FontFormatException ex) @@ -79,6 +92,25 @@ public class FontManager } } + public static Font getFontOffCorrectSize(Font f) + { + // Size of the font is already set + if (f.getSize2D() > 1) + { + return f; + } + + // Dummy canvas for font metrics + Canvas c = new Canvas(); + + f = f.deriveFont(12f); + if (c.getFontMetrics(f).getMaxAscent() > 11) + { + f = f.deriveFont(11f); + } + return f; + } + public static Font getRunescapeFont() { return runescapeFont; @@ -93,4 +125,63 @@ public class FontManager { return runescapeBoldFont; } -} + + private static boolean isRunescapeFont(Font f) + { + return f.equals(runescapeFont) || f.equals(runescapeSmallFont) || f.equals(runescapeBoldFont); + } + + public static Font getFontFromType(Font f, FontType type) + { + switch (type) + { + case SMALL: + if (isRunescapeFont(f)) + { + return runescapeSmallFont; + } + return getFontOrDefault(f); + case BOLD: + if (isRunescapeFont(f)) + { + return runescapeBoldFont; + } + return getFontOrDefault(f).deriveFont(Font.BOLD, 14.0f); + default: //in this case regular + if (isRunescapeFont(f)) + { + return runescapeFont; + } + return getFontOrDefault(f).deriveFont(14.0f); + } + } + + public static Font lookupFont(String fontName) + { + return fontMap.get(fontName); + } + + public static String getFontName(Font font) + { + return fontMap.inverse().get(font); + } + + public static String[] getAvailableFontNames() + { + return fontMap.keySet().toArray(new String[fontMap.keySet().size()]); + } + + public static boolean isAvailable(Font font) + { + return fontMap.containsKey(font.getFontName()); + } + + public static Font getFontOrDefault(Font font) + { + if (font == null || !fontMap.containsKey(font.getFontName())) + { + return getRunescapeFont(); + } + return getFontOffCorrectSize(font); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java index eb817354b7..06405dea83 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java @@ -56,6 +56,7 @@ import net.runelite.client.input.MouseAdapter; import net.runelite.client.input.MouseManager; import net.runelite.client.ui.JagexColors; import net.runelite.client.util.ColorUtil; +import net.runelite.client.ui.FontManager; @Singleton public class OverlayRenderer extends MouseAdapter implements KeyListener @@ -456,15 +457,15 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener // Set font based on configuration if (position == OverlayPosition.DYNAMIC || position == OverlayPosition.DETACHED) { - subGraphics.setFont(runeLiteConfig.fontType().getFont()); + subGraphics.setFont(FontManager.getFontFromType(runeLiteConfig.clientFont(), runeLiteConfig.fontType())); } else if (position == OverlayPosition.TOOLTIP) { - subGraphics.setFont(runeLiteConfig.tooltipFontType().getFont()); + subGraphics.setFont(FontManager.getFontFromType(runeLiteConfig.clientFont(), runeLiteConfig.tooltipFontType())); } else { - subGraphics.setFont(runeLiteConfig.interfaceFontType().getFont()); + subGraphics.setFont(FontManager.getFontFromType(runeLiteConfig.clientFont(), runeLiteConfig.interfaceFontType())); } subGraphics.translate(point.x, point.y);