From 35689961384465d20880d41cd008727bcefb5d2d Mon Sep 17 00:00:00 2001 From: froslanz Date: Thu, 22 Oct 2026 12:54:00 -0400 Subject: [PATCH] center clickgui text by the font's cap band instead of vanilla offsets button labels, panel titles and the color picker's copy/paste text used y offsets hand-tuned for vanilla's 9px line box, so the custom font's 14px line box rendered text ~4px too low, poking out below 15px buttons and over the header accent line. FrosFont now measures the distance from line top to the middle of the cap band (glyph 'A' visual bounds) and all labels center on that via FrosFont.visualCenter()/Item.textY(). the vanilla fallback lands on the exact old offsets, so nothing moves when fonts are disabled, and the legacy getTextOffset() hack is gone --- .../java/cc/fros/features/gui/FrosGui.java | 4 --- .../java/cc/fros/features/gui/Widget.java | 3 ++- .../java/cc/fros/features/gui/items/Item.java | 5 ++++ .../gui/items/buttons/BindButton.java | 5 ++-- .../gui/items/buttons/BooleanButton.java | 3 +-- .../features/gui/items/buttons/Button.java | 2 +- .../gui/items/buttons/ColorButton.java | 6 ++--- .../gui/items/buttons/EnumButton.java | 3 +-- .../features/gui/items/buttons/Slider.java | 2 +- .../gui/items/buttons/StringButton.java | 5 ++-- .../java/cc/fros/util/render/FrosFont.java | 25 +++++++++++++++++++ 11 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/main/java/cc/fros/features/gui/FrosGui.java b/src/main/java/cc/fros/features/gui/FrosGui.java index 3157ff0..7b328cc 100644 --- a/src/main/java/cc/fros/features/gui/FrosGui.java +++ b/src/main/java/cc/fros/features/gui/FrosGui.java @@ -146,10 +146,6 @@ public class FrosGui extends Screen { return this.widgets; } - public int getTextOffset() { - return -6; - } - public static Color getColorClipboard() { return colorClipboard; } diff --git a/src/main/java/cc/fros/features/gui/Widget.java b/src/main/java/cc/fros/features/gui/Widget.java index 601ddd7..96acc6a 100644 --- a/src/main/java/cc/fros/features/gui/Widget.java +++ b/src/main/java/cc/fros/features/gui/Widget.java @@ -77,7 +77,8 @@ public class Widget RenderUtil.rect(context, this.x, headerTop, this.x + this.width, panelBottom, 0x99000000, 1.0f); context.fill(this.x, headerBottom - 1, this.x + this.width, headerBottom, accent); - drawString(this.getName(), (float) this.x + 3.0f, (float) this.y - 4.0f - (float) FrosGui.getClickGui().getTextOffset(), -1); + drawString(this.getName(), (float) this.x + 3.0f, + (headerTop + headerBottom) / 2f - FrosFont.visualCenter(), -1); ScissorUtil.enable(context, x, 0, x + width, mc.getWindow().getGuiScaledHeight()); if (this.open) { diff --git a/src/main/java/cc/fros/features/gui/items/Item.java b/src/main/java/cc/fros/features/gui/items/Item.java index 52d1832..aed719c 100644 --- a/src/main/java/cc/fros/features/gui/items/Item.java +++ b/src/main/java/cc/fros/features/gui/items/Item.java @@ -83,6 +83,11 @@ public class Item FrosFont.draw(context, text, (int) x, (int) y, color); } + /** y coordinate that visually centers text inside this item */ + protected float textY() { + return this.y + this.height / 2f - FrosFont.visualCenter(); + } + public boolean isHovering(int mouseX, int mouseY) { return false; } diff --git a/src/main/java/cc/fros/features/gui/items/buttons/BindButton.java b/src/main/java/cc/fros/features/gui/items/buttons/BindButton.java index be8b565..b50c4c2 100644 --- a/src/main/java/cc/fros/features/gui/items/buttons/BindButton.java +++ b/src/main/java/cc/fros/features/gui/items/buttons/BindButton.java @@ -1,7 +1,6 @@ package cc.fros.features.gui.items.buttons; import cc.fros.Fros; -import cc.fros.features.gui.FrosGui; import cc.fros.features.modules.client.ClickGuiModule; import cc.fros.features.settings.Bind; import cc.fros.features.settings.Setting; @@ -29,10 +28,10 @@ public class BindButton int color = ClickGuiModule.getInstance().color.getValue().getRGB(); RenderUtil.rect(context, this.x, this.y, this.x + (float) this.width + 7.4f, this.y + (float) this.height - 0.5f, this.getState() ? (!this.isHovering(mouseX, mouseY) ? 0x11555555 : -2007673515) : (!this.isHovering(mouseX, mouseY) ? Fros.colorManager.getColorWithAlpha(y, ClickGuiModule.getInstance().color.getValue().getAlpha()) : Fros.colorManager.getColorWithAlpha(y, ClickGuiModule.getInstance().topColor.getValue().getAlpha()))); if (this.isListening) { - drawString(context, "Press a Key...", this.x + 2.3f, this.y - 1.7f - (float) FrosGui.getClickGui().getTextOffset(), -1); + drawString(context, "Press a Key...", this.x + 2.3f, textY(), -1); } else { String str = KeyboardUtil.getKeyName(setting.getValue()); - drawString(context, this.setting.getName() + " " + ChatFormatting.GRAY + str, this.x + 2.3f, this.y - 1.7f - (float) FrosGui.getClickGui().getTextOffset(), this.getState() ? -1 : -5592406); + drawString(context, this.setting.getName() + " " + ChatFormatting.GRAY + str, this.x + 2.3f, textY(), this.getState() ? -1 : -5592406); } } diff --git a/src/main/java/cc/fros/features/gui/items/buttons/BooleanButton.java b/src/main/java/cc/fros/features/gui/items/buttons/BooleanButton.java index 2bd00f5..b426c01 100644 --- a/src/main/java/cc/fros/features/gui/items/buttons/BooleanButton.java +++ b/src/main/java/cc/fros/features/gui/items/buttons/BooleanButton.java @@ -2,7 +2,6 @@ package cc.fros.features.gui.items.buttons; import cc.fros.Fros; -import cc.fros.features.gui.FrosGui; import cc.fros.features.modules.client.ClickGuiModule; import cc.fros.features.settings.Setting; import cc.fros.util.render.RenderUtil; @@ -23,7 +22,7 @@ public class BooleanButton @Override public void drawScreen(GuiGraphics context, int mouseX, int mouseY, float partialTicks) { RenderUtil.rect(context, this.x, this.y, this.x + (float) this.width + 7.4f, this.y + (float) this.height - 0.5f, this.getState() ? (!this.isHovering(mouseX, mouseY) ? Fros.colorManager.getColorWithAlpha(y, ClickGuiModule.getInstance().color.getValue().getAlpha()) : Fros.colorManager.getColorWithAlpha(y, ClickGuiModule.getInstance().topColor.getValue().getAlpha())) : (!this.isHovering(mouseX, mouseY) ? 0x11555555 : -2007673515)); - drawString(context, this.getName(), this.x + 2.3f, this.y - 1.7f - (float) FrosGui.getClickGui().getTextOffset(), this.getState() ? -1 : -5592406); + drawString(context, this.getName(), this.x + 2.3f, textY(), this.getState() ? -1 : -5592406); } @Override diff --git a/src/main/java/cc/fros/features/gui/items/buttons/Button.java b/src/main/java/cc/fros/features/gui/items/buttons/Button.java index 589c096..d114e68 100644 --- a/src/main/java/cc/fros/features/gui/items/buttons/Button.java +++ b/src/main/java/cc/fros/features/gui/items/buttons/Button.java @@ -22,7 +22,7 @@ public class Button @Override public void drawScreen(GuiGraphics context, int mouseX, int mouseY, float partialTicks) { RenderUtil.rect(context, this.x, this.y, this.x + (float) this.width, this.y + (float) this.height - 0.5f, this.getState() ? (!this.isHovering(mouseX, mouseY) ? Fros.colorManager.getColorWithAlpha(y, ClickGuiModule.getInstance().color.getValue().getAlpha()) : Fros.colorManager.getColorWithAlpha(y, ClickGuiModule.getInstance().topColor.getValue().getAlpha())) : (!this.isHovering(mouseX, mouseY) ? 0x11555555 : -2007673515)); - drawString(context, this.getName(), this.x + 2.3f, this.y - 2.0f - (float) FrosGui.getClickGui().getTextOffset(), this.getState() ? -1 : -5592406); + drawString(context, this.getName(), this.x + 2.3f, textY(), this.getState() ? -1 : -5592406); } @Override diff --git a/src/main/java/cc/fros/features/gui/items/buttons/ColorButton.java b/src/main/java/cc/fros/features/gui/items/buttons/ColorButton.java index 2bddd56..f6b2475 100644 --- a/src/main/java/cc/fros/features/gui/items/buttons/ColorButton.java +++ b/src/main/java/cc/fros/features/gui/items/buttons/ColorButton.java @@ -44,7 +44,7 @@ public class ColorButton extends Button { this.x + (float) this.width + 5.0f, this.y + (float) this.height - 2.5f, new Color(currentColor.getRGB(), false).getRGB()); - drawString(context, this.getName(), this.x + 2.3f, this.y - 1.7f - (float) FrosGui.getClickGui().getTextOffset(), -1); + drawString(context, this.getName(), this.x + 2.3f, textY(), -1); if (open) { float yOffset = this.height + 1; @@ -121,12 +121,12 @@ public class ColorButton extends Button { int buttonWidth = availableWidth / 2; RenderUtil.rect(context, pickerX, this.y + yOffset, pickerX + buttonWidth, this.y + yOffset + 14, hoveringCopy ? Fros.colorManager.getColorWithAlpha(y, ClickGuiModule.getInstance().topColor.getValue().getAlpha()) : 0x11555555); - drawString(context, "Copy", pickerX + buttonWidth / 2.0 - FrosFont.width("Copy") / 2.0, this.y + yOffset + 3, -1); + drawString(context, "Copy", pickerX + buttonWidth / 2.0 - FrosFont.width("Copy") / 2.0, this.y + yOffset + 7f - FrosFont.visualCenter(), -1); hoveringCopy = isHoveringArea(mouseX, mouseY, pickerX, this.y + yOffset, pickerX + buttonWidth, this.y + yOffset + 14); RenderUtil.rect(context, pickerX + buttonWidth + 1, this.y + yOffset, pickerX + buttonWidth * 2 + 1, this.y + yOffset + 14, hoveringPaste ? Fros.colorManager.getColorWithAlpha(y, ClickGuiModule.getInstance().topColor.getValue().getAlpha()) : 0x11555555); - drawString(context, "Paste", pickerX + buttonWidth + buttonWidth / 2.0 - FrosFont.width("Paste") / 2.0 + 1, this.y + yOffset + 3, -1); + drawString(context, "Paste", pickerX + buttonWidth + buttonWidth / 2.0 - FrosFont.width("Paste") / 2.0 + 1, this.y + yOffset + 7f - FrosFont.visualCenter(), -1); hoveringPaste = isHoveringArea(mouseX, mouseY, pickerX + buttonWidth + 1, this.y + yOffset, pickerX + buttonWidth * 2 + 1, this.y + yOffset + 14); } } diff --git a/src/main/java/cc/fros/features/gui/items/buttons/EnumButton.java b/src/main/java/cc/fros/features/gui/items/buttons/EnumButton.java index dbfeef5..5f07930 100644 --- a/src/main/java/cc/fros/features/gui/items/buttons/EnumButton.java +++ b/src/main/java/cc/fros/features/gui/items/buttons/EnumButton.java @@ -2,7 +2,6 @@ package cc.fros.features.gui.items.buttons; import cc.fros.Fros; -import cc.fros.features.gui.FrosGui; import cc.fros.features.modules.client.ClickGuiModule; import cc.fros.features.settings.Setting; import cc.fros.util.render.RenderUtil; @@ -24,7 +23,7 @@ public class EnumButton @Override public void drawScreen(GuiGraphics context, int mouseX, int mouseY, float partialTicks) { RenderUtil.rect(context, this.x, this.y, this.x + (float) this.width + 7.4f, this.y + (float) this.height - 0.5f, this.getState() ? (!this.isHovering(mouseX, mouseY) ? Fros.colorManager.getColorWithAlpha(y, ClickGuiModule.getInstance().color.getValue().getAlpha()) : Fros.colorManager.getColorWithAlpha(y, ClickGuiModule.getInstance().topColor.getValue().getAlpha())) : (!this.isHovering(mouseX, mouseY) ? 0x11555555 : -2007673515)); - drawString(context, this.setting.getName() + " " + ChatFormatting.GRAY + (this.setting.currentEnumName().equalsIgnoreCase("ABC") ? "ABC" : this.setting.currentEnumName()), this.x + 2.3f, this.y - 1.7f - (float) FrosGui.getClickGui().getTextOffset(), this.getState() ? -1 : -5592406); + drawString(context, this.setting.getName() + " " + ChatFormatting.GRAY + (this.setting.currentEnumName().equalsIgnoreCase("ABC") ? "ABC" : this.setting.currentEnumName()), this.x + 2.3f, textY(), this.getState() ? -1 : -5592406); } @Override diff --git a/src/main/java/cc/fros/features/gui/items/buttons/Slider.java b/src/main/java/cc/fros/features/gui/items/buttons/Slider.java index 233e0df..6477fad 100644 --- a/src/main/java/cc/fros/features/gui/items/buttons/Slider.java +++ b/src/main/java/cc/fros/features/gui/items/buttons/Slider.java @@ -32,7 +32,7 @@ public class Slider this.dragSetting(mouseX, mouseY); RenderUtil.rect(context, this.x, this.y, this.x + (float) this.width + 7.4f, this.y + (float) this.height - 0.5f, !(this.dragging || this.isHovering(mouseX, mouseY)) ? 0x11555555 : -2007673515); RenderUtil.rect(context, this.x, this.y, (this.setting.getValue()).floatValue() <= this.min.floatValue() ? this.x : this.x + ((float) this.width + 7.4f) * this.partialMultiplier(), this.y + (float) this.height - 0.5f, !(this.dragging || this.isHovering(mouseX, mouseY)) ? Fros.colorManager.getColorWithAlpha(y, ClickGuiModule.getInstance().color.getValue().getAlpha()) : Fros.colorManager.getColorWithAlpha(y, ClickGuiModule.getInstance().topColor.getValue().getAlpha())); - drawString(context, this.getName() + " " + ChatFormatting.GRAY + (this.setting.getValue() instanceof Float ? this.setting.getValue() : Double.valueOf((this.setting.getValue()).doubleValue())), this.x + 2.3f, this.y - 1.7f - (float) FrosGui.getClickGui().getTextOffset(), -1); + drawString(context, this.getName() + " " + ChatFormatting.GRAY + (this.setting.getValue() instanceof Float ? this.setting.getValue() : Double.valueOf((this.setting.getValue()).doubleValue())), this.x + 2.3f, textY(), -1); } @Override diff --git a/src/main/java/cc/fros/features/gui/items/buttons/StringButton.java b/src/main/java/cc/fros/features/gui/items/buttons/StringButton.java index b01f94d..59b7d33 100644 --- a/src/main/java/cc/fros/features/gui/items/buttons/StringButton.java +++ b/src/main/java/cc/fros/features/gui/items/buttons/StringButton.java @@ -1,7 +1,6 @@ package cc.fros.features.gui.items.buttons; import cc.fros.Fros; -import cc.fros.features.gui.FrosGui; import cc.fros.features.modules.client.ClickGuiModule; import cc.fros.features.settings.Setting; import cc.fros.util.models.Timer; @@ -38,9 +37,9 @@ public class StringButton public void drawScreen(GuiGraphics context, int mouseX, int mouseY, float partialTicks) { RenderUtil.rect(context, this.x, this.y, this.x + (float) this.width + 7.4f, this.y + (float) this.height - 0.5f, this.getState() ? (!this.isHovering(mouseX, mouseY) ? Fros.colorManager.getColorWithAlpha(y, ClickGuiModule.getInstance().color.getValue().getAlpha()) : Fros.colorManager.getColorWithAlpha(y, ClickGuiModule.getInstance().topColor.getValue().getAlpha())) : (!this.isHovering(mouseX, mouseY) ? 0x11555555 : -2007673515)); if (this.isListening) { - drawString(context, this.currentString.string() + getIdleSign(), this.x + 2.3f, this.y - 1.7f - (float) FrosGui.getClickGui().getTextOffset(), this.getState() ? -1 : -5592406); + drawString(context, this.currentString.string() + getIdleSign(), this.x + 2.3f, textY(), this.getState() ? -1 : -5592406); } else { - drawString(context, (this.setting.getName().equals("Buttons") ? "Buttons " : (this.setting.getName().equals("Prefix") ? "Prefix " + ChatFormatting.GRAY : "")) + this.setting.getValue(), this.x + 2.3f, this.y - 1.7f - (float) FrosGui.getClickGui().getTextOffset(), this.getState() ? -1 : -5592406); + drawString(context, (this.setting.getName().equals("Buttons") ? "Buttons " : (this.setting.getName().equals("Prefix") ? "Prefix " + ChatFormatting.GRAY : "")) + this.setting.getValue(), this.x + 2.3f, textY(), this.getState() ? -1 : -5592406); } } diff --git a/src/main/java/cc/fros/util/render/FrosFont.java b/src/main/java/cc/fros/util/render/FrosFont.java index 85fb454..2a0433e 100644 --- a/src/main/java/cc/fros/util/render/FrosFont.java +++ b/src/main/java/cc/fros/util/render/FrosFont.java @@ -83,6 +83,8 @@ public final class FrosFont { private static String loadedName; private static float loadedSize = Float.NaN; private static float loadedScale = 1; + /** raster pixels from the top of a line box to the middle of the cap band */ + private static float visualCenterRaster = 4f; private static long lastAttempt; private static int glyphCounter; @@ -218,10 +220,33 @@ public final class FrosFont { Graphics2D graphics = probe.createGraphics(); graphics.setFont(awtFont); metrics = graphics.getFontMetrics(); + // distance from the top of the line box to the middle of the cap band: + // drawString puts the baseline at metrics.getAscent(), and "A" spans + // from the baseline up to the cap line + java.awt.geom.Rectangle2D capBounds = awtFont + .createGlyphVector(graphics.getFontRenderContext(), "A") + .getVisualBounds(); + float capHeight = (float) capBounds.getHeight(); + if (capHeight <= 0f || capHeight > metrics.getAscent()) { + capHeight = metrics.getAscent(); + } + visualCenterRaster = metrics.getAscent() - capHeight / 2f; graphics.dispose(); if (verbose) LOGGER.info("{} ({}pt)", source, size); } + /** + * Distance from the top of a line box down to the visual center of its + * text (middle of the cap band), in gui units. lets callers center labels + * by what the eye sees instead of the line box, and behaves the same for + * the custom font and the vanilla fallback. + */ + public static float visualCenter() { + sync(); + if (awtFont == null) return mc.font.lineHeight / 2f - 1f; + return visualCenterRaster / loadedScale; + } + /** * Resolves java's logical fonts (guaranteed on every os) and any font * family already installed on the system, without needing a file.