From ca56ef10823aea1ecd275c0d3c3f9a3b17838ff9 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 30 Jan 2021 13:14:33 -0500 Subject: [PATCH] Apply default font to text with unicode characters MacOS does not support fallback fonts, and any character not in our RS fonts do not render correctly. We only render unicode characters a handful of places, mostly for the check mark/cross in overlays, and on the icon text field suggestion button. So this sets the font of those places to the default system font which can render them correctly. --- .../barrows/BarrowsBrotherSlainOverlay.java | 2 ++ .../plugins/cluescrolls/clues/EmoteClue.java | 5 ++- .../cluescrolls/clues/FaloTheBardClue.java | 2 ++ .../cluescrolls/clues/SkillChallengeClue.java | 18 +++++----- .../net/runelite/client/ui/FontManager.java | 36 +++++++++---------- .../client/ui/components/IconTextField.java | 9 ++--- .../ui/overlay/components/LineComponent.java | 30 +++++++++++----- .../ui/overlay/components/TextComponent.java | 24 ++++++++++++- 8 files changed, 83 insertions(+), 43 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsBrotherSlainOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsBrotherSlainOverlay.java index c7cdef0058..4e4eba0175 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsBrotherSlainOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsBrotherSlainOverlay.java @@ -34,6 +34,7 @@ import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; import net.runelite.api.Varbits; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.ui.FontManager; import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; import net.runelite.client.ui.overlay.OverlayMenuEntry; import net.runelite.client.ui.overlay.OverlayPanel; @@ -82,6 +83,7 @@ public class BarrowsBrotherSlainOverlay extends OverlayPanel panelComponent.getChildren().add(LineComponent.builder() .left(brother.getName()) .right(slain) + .rightFont(FontManager.getDefaultFont()) .rightColor(brotherSlain ? Color.GREEN : Color.RED) .build()); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java index b59be0da14..ab3ac38982 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java @@ -45,6 +45,7 @@ import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldPoint; import static net.runelite.client.plugins.cluescrolls.ClueScrollOverlay.TITLED_CONTENT_COLOR; import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; +import static net.runelite.client.plugins.cluescrolls.clues.Enemy.*; import net.runelite.client.plugins.cluescrolls.clues.emote.Emote; import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.*; import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.BULL_ROARER; @@ -53,7 +54,7 @@ import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.*; import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SHANTAY_PASS; import net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirement; import static net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirements.*; -import static net.runelite.client.plugins.cluescrolls.clues.Enemy.*; +import net.runelite.client.ui.FontManager; import net.runelite.client.ui.overlay.OverlayUtil; import net.runelite.client.ui.overlay.components.LineComponent; import net.runelite.client.ui.overlay.components.PanelComponent; @@ -258,6 +259,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu panelComponent.getChildren().add(LineComponent.builder() .left("STASH Unit:") .right(stashUnitBuilt ? UNICODE_CHECK_MARK : UNICODE_BALLOT_X) + .rightFont(FontManager.getDefaultFont()) .rightColor(stashUnitBuilt ? Color.GREEN : Color.RED) .build()); } @@ -292,6 +294,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu .left(requirement.getCollectiveName(client)) .leftColor(TITLED_CONTENT_COLOR) .right(combinedFulfilled ? UNICODE_CHECK_MARK : UNICODE_BALLOT_X) + .rightFont(FontManager.getDefaultFont()) .rightColor(equipmentFulfilled ? Color.GREEN : (combinedFulfilled ? Color.ORANGE : Color.RED)) .build()); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/FaloTheBardClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/FaloTheBardClue.java index 16974ffd16..c208d5238f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/FaloTheBardClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/FaloTheBardClue.java @@ -41,6 +41,7 @@ import net.runelite.client.plugins.cluescrolls.clues.item.AnyRequirementCollecti import net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirement; import net.runelite.client.plugins.cluescrolls.clues.item.RangeItemRequirement; import net.runelite.client.plugins.cluescrolls.clues.item.SingleItemRequirement; +import net.runelite.client.ui.FontManager; import net.runelite.client.ui.overlay.OverlayUtil; import net.runelite.client.ui.overlay.components.LineComponent; import net.runelite.client.ui.overlay.components.PanelComponent; @@ -134,6 +135,7 @@ public class FaloTheBardClue extends ClueScroll implements TextClueScroll, NpcCl .left(requirement.getCollectiveName(plugin.getClient())) .leftColor(TITLED_CONTENT_COLOR) .right(inventoryFulfilled ? "\u2713" : "\u2717") + .rightFont(FontManager.getDefaultFont()) .rightColor(inventoryFulfilled ? Color.GREEN : Color.RED) .build()); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java index 67de8ad26a..41f6f283cb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java @@ -25,6 +25,11 @@ package net.runelite.client.plugins.cluescrolls.clues; import com.google.common.collect.ImmutableSet; +import java.awt.Color; +import java.awt.Graphics2D; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; @@ -34,25 +39,21 @@ import net.runelite.api.ItemID; import net.runelite.api.NPC; import net.runelite.api.Point; import net.runelite.api.TileObject; +import static net.runelite.client.plugins.cluescrolls.ClueScrollOverlay.TITLED_CONTENT_COLOR; import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.CLICKBOX_BORDER_COLOR; import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.CLICKBOX_FILL_COLOR; import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.CLICKBOX_HOVER_BORDER_COLOR; +import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.IMAGE_Z_OFFSET; import net.runelite.client.plugins.cluescrolls.clues.item.AnyRequirementCollection; -import static net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirements.*; import net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirement; +import static net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirements.*; import net.runelite.client.plugins.cluescrolls.clues.item.SingleItemRequirement; +import net.runelite.client.ui.FontManager; import net.runelite.client.ui.overlay.OverlayUtil; import net.runelite.client.ui.overlay.components.LineComponent; import net.runelite.client.ui.overlay.components.PanelComponent; import net.runelite.client.ui.overlay.components.TitleComponent; -import java.awt.Color; -import java.awt.Graphics2D; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import static net.runelite.client.plugins.cluescrolls.ClueScrollOverlay.TITLED_CONTENT_COLOR; -import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.IMAGE_Z_OFFSET; @Getter public class SkillChallengeClue extends ClueScroll implements NpcClueScroll, NamedObjectClueScroll @@ -379,6 +380,7 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll, Nam .left(requirement.getCollectiveName(plugin.getClient())) .leftColor(TITLED_CONTENT_COLOR) .right(combinedFulfilled ? "\u2713" : "\u2717") + .rightFont(FontManager.getDefaultFont()) .rightColor(equipmentFulfilled || (combinedFulfilled && !requireEquipped) ? Color.GREEN : (combinedFulfilled ? Color.ORANGE : Color.RED)) .build()); } 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 564ebcba62..5305506a41 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,17 +24,25 @@ */ package net.runelite.client.ui; -import javax.swing.text.StyleContext; import java.awt.Font; import java.awt.FontFormatException; import java.awt.GraphicsEnvironment; import java.io.IOException; +import javax.swing.text.StyleContext; +import lombok.Getter; public class FontManager { + @Getter private static final Font runescapeFont; + @Getter private static final Font runescapeSmallFont; + @Getter private static final Font runescapeBoldFont; + @Getter + private static final Font defaultFont; + @Getter + private static final Font defaultBoldFont; static { @@ -48,7 +56,7 @@ public class FontManager ge.registerFont(font); runescapeFont = StyleContext.getDefaultStyleContext() - .getFont(font.getName(), Font.PLAIN, 16); + .getFont(font.getName(), Font.PLAIN, 16); ge.registerFont(runescapeFont); Font smallFont = Font.createFont(Font.TRUETYPE_FONT, @@ -57,16 +65,16 @@ public class FontManager ge.registerFont(smallFont); runescapeSmallFont = StyleContext.getDefaultStyleContext() - .getFont(smallFont.getName(), Font.PLAIN, 16); + .getFont(smallFont.getName(), Font.PLAIN, 16); ge.registerFont(runescapeSmallFont); Font boldFont = Font.createFont(Font.TRUETYPE_FONT, - FontManager.class.getResourceAsStream("runescape_bold.ttf")) - .deriveFont(Font.BOLD, 16); + FontManager.class.getResourceAsStream("runescape_bold.ttf")) + .deriveFont(Font.BOLD, 16); ge.registerFont(boldFont); runescapeBoldFont = StyleContext.getDefaultStyleContext() - .getFont(boldFont.getName(), Font.BOLD, 16); + .getFont(boldFont.getName(), Font.BOLD, 16); ge.registerFont(runescapeBoldFont); } catch (FontFormatException ex) @@ -77,20 +85,8 @@ public class FontManager { throw new RuntimeException("Font file not found.", ex); } - } - public static Font getRunescapeFont() - { - return runescapeFont; - } - - public static Font getRunescapeSmallFont() - { - return runescapeSmallFont; - } - - public static Font getRunescapeBoldFont() - { - return runescapeBoldFont; + defaultFont = new Font(Font.DIALOG, Font.PLAIN, 16); + defaultBoldFont = new Font(Font.DIALOG, Font.BOLD, 16); } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/IconTextField.java b/runelite-client/src/main/java/net/runelite/client/ui/components/IconTextField.java index cb317b8afd..b4c2ff1127 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/components/IconTextField.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/IconTextField.java @@ -29,6 +29,7 @@ package net.runelite.client.ui.components; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; +import java.awt.Font; import java.awt.event.ActionListener; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; @@ -125,7 +126,7 @@ public class IconTextField extends JPanel textField.addMouseListener(hoverEffect); innerTxt.addMouseListener(hoverEffect); - clearButton = createRHSButton(ColorScheme.PROGRESS_ERROR_COLOR, Color.PINK); + clearButton = createRHSButton(ColorScheme.PROGRESS_ERROR_COLOR, Color.PINK, FontManager.getRunescapeBoldFont()); clearButton.setText("×"); clearButton.addActionListener(evt -> { @@ -192,7 +193,7 @@ public class IconTextField extends JPanel } }); - suggestionButton = createRHSButton(ColorScheme.LIGHT_GRAY_COLOR, ColorScheme.MEDIUM_GRAY_COLOR); + suggestionButton = createRHSButton(ColorScheme.LIGHT_GRAY_COLOR, ColorScheme.MEDIUM_GRAY_COLOR, FontManager.getDefaultBoldFont()); suggestionButton.setText("▾"); suggestionButton.addActionListener(e -> { @@ -237,11 +238,11 @@ public class IconTextField extends JPanel add(rhsButtons, BorderLayout.EAST); } - private JButton createRHSButton(Color fg, Color rollover) + private JButton createRHSButton(Color fg, Color rollover, Font font) { JButton b = new JButton(); b.setPreferredSize(new Dimension(30, 0)); - b.setFont(FontManager.getRunescapeBoldFont()); + b.setFont(font); b.setBorder(null); b.setRolloverEnabled(true); SwingUtil.removeButtonDecorations(b); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java index 20638e7874..83c67c09e0 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java @@ -28,6 +28,7 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Strings; import java.awt.Color; import java.awt.Dimension; +import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Point; @@ -50,6 +51,10 @@ public class LineComponent implements LayoutableRenderableEntity @Builder.Default private Color rightColor = Color.WHITE; + private Font leftFont; + + private Font rightFont; + @Builder.Default private Point preferredLocation = new Point(); @@ -67,13 +72,16 @@ public class LineComponent implements LayoutableRenderableEntity final String left = MoreObjects.firstNonNull(this.left, ""); final String right = MoreObjects.firstNonNull(this.right, ""); - final FontMetrics metrics = graphics.getFontMetrics(); + final Font leftFont = MoreObjects.firstNonNull(this.leftFont, graphics.getFont()); + final Font rightFont = MoreObjects.firstNonNull(this.rightFont, graphics.getFont()); + final FontMetrics lfm = graphics.getFontMetrics(leftFont), rfm = graphics.getFontMetrics(rightFont); + final int fmHeight = Math.max(lfm.getHeight(), rfm.getHeight()); final int baseX = preferredLocation.x; - final int baseY = preferredLocation.y + metrics.getHeight(); + final int baseY = preferredLocation.y + fmHeight; int x = baseX; int y = baseY; - final int leftFullWidth = getLineWidth(left, metrics); - final int rightFullWidth = getLineWidth(right, metrics); + final int leftFullWidth = getLineWidth(left, lfm); + final int rightFullWidth = getLineWidth(right, rfm); final TextComponent textComponent = new TextComponent(); if (preferredSize.width < leftFullWidth + rightFullWidth) @@ -87,8 +95,8 @@ public class LineComponent implements LayoutableRenderableEntity leftSmallWidth -= rightSmallWidth; } - final String[] leftSplitLines = lineBreakText(left, leftSmallWidth, metrics); - final String[] rightSplitLines = lineBreakText(right, rightSmallWidth, metrics); + final String[] leftSplitLines = lineBreakText(left, leftSmallWidth, lfm); + final String[] rightSplitLines = lineBreakText(right, rightSmallWidth, rfm); int lineCount = Math.max(leftSplitLines.length, rightSplitLines.length); @@ -100,19 +108,21 @@ public class LineComponent implements LayoutableRenderableEntity textComponent.setPosition(new Point(x, y)); textComponent.setText(leftText); textComponent.setColor(leftColor); + textComponent.setFont(leftFont); textComponent.render(graphics); } if (i < rightSplitLines.length) { final String rightText = rightSplitLines[i]; - textComponent.setPosition(new Point(x + preferredSize.width - getLineWidth(rightText, metrics), y)); + textComponent.setPosition(new Point(x + preferredSize.width - getLineWidth(rightText, rfm), y)); textComponent.setText(rightText); textComponent.setColor(rightColor); + textComponent.setFont(rightFont); textComponent.render(graphics); } - y += metrics.getHeight(); + y += fmHeight; } final Dimension dimension = new Dimension(preferredSize.width, y - baseY); @@ -126,6 +136,7 @@ public class LineComponent implements LayoutableRenderableEntity textComponent.setPosition(new Point(x, y)); textComponent.setText(left); textComponent.setColor(leftColor); + textComponent.setFont(leftFont); textComponent.render(graphics); } @@ -134,10 +145,11 @@ public class LineComponent implements LayoutableRenderableEntity textComponent.setPosition(new Point(x + preferredSize.width - rightFullWidth, y)); textComponent.setText(right); textComponent.setColor(rightColor); + textComponent.setFont(rightFont); textComponent.render(graphics); } - y += metrics.getHeight(); + y += fmHeight; final Dimension dimension = new Dimension(preferredSize.width, y - baseY); bounds.setLocation(preferredLocation); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TextComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TextComponent.java index 45326fea28..0b6054a466 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TextComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TextComponent.java @@ -26,10 +26,12 @@ package net.runelite.client.ui.overlay.components; import java.awt.Color; import java.awt.Dimension; +import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Point; import java.util.regex.Pattern; +import javax.annotation.Nullable; import lombok.Setter; import net.runelite.client.ui.overlay.RenderableEntity; import net.runelite.client.util.ColorUtil; @@ -45,10 +47,22 @@ public class TextComponent implements RenderableEntity private Point position = new Point(); private Color color = Color.WHITE; private boolean outline; + /** + * The text font. + */ + @Nullable + private Font font; @Override public Dimension render(Graphics2D graphics) { + Font originalFont = null; + if (font != null) + { + originalFont = graphics.getFont(); + graphics.setFont(font); + } + final FontMetrics fontMetrics = graphics.getFontMetrics(); if (COL_TAG_PATTERN_W_LOOKAHEAD.matcher(text).find()) @@ -105,6 +119,14 @@ public class TextComponent implements RenderableEntity graphics.drawString(text, position.x, position.y); } - return new Dimension(fontMetrics.stringWidth(text), fontMetrics.getHeight()); + int width = fontMetrics.stringWidth(text); + int height = fontMetrics.getHeight(); + + if (originalFont != null) + { + graphics.setFont(originalFont); + } + + return new Dimension(width, height); } }