Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

blazingly fast bordered text renderer ⚡ #347

Open
wants to merge 8 commits into
base: develop-v0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/OneConfig.api
Original file line number Diff line number Diff line change
Expand Up @@ -1263,6 +1263,7 @@ public class cc/polyfrost/oneconfig/images/OneImage {
public abstract interface class cc/polyfrost/oneconfig/platform/GLPlatform {
public abstract fun drawRect (FFFFI)V
public abstract fun drawText (Lcc/polyfrost/oneconfig/libs/universal/UMatrixStack;Ljava/lang/String;FFIZ)F
public abstract fun drawText (Ljava/lang/String;FFILcc/polyfrost/oneconfig/renderer/TextRenderer$TextType;)F
public fun drawText (Ljava/lang/String;FFIZ)F
public abstract fun enableStencil ()V
public abstract fun getStringWidth (Ljava/lang/String;)I
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,4 @@ apiValidation {
ignoredPackages.add("cc.polyfrost.oneconfig.libs")
ignoredPackages.add("cc.polyfrost.oneconfig.internal")
ignoredPackages.add("cc.polyfrost.oneconfig.test")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ public class Preferences extends InternalConfig {
)
public static float customScale = 1f;

@Switch(
name = "Optimized Font Renderer",
subcategory = "GUI Settings",
description = "May be incompatible with some mods"
)
public static boolean optimizedFontRenderer = true;

@Dropdown(
name = "Opening Behavior",
category = "Behavior",
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/cc/polyfrost/oneconfig/platform/GLPlatform.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
package cc.polyfrost.oneconfig.platform;

import cc.polyfrost.oneconfig.libs.universal.UMatrixStack;
import cc.polyfrost.oneconfig.renderer.TextRenderer;

public interface GLPlatform {
void drawRect(float x, float y, float x2, float y2, int color);
Expand All @@ -37,6 +38,8 @@ default float drawText(String text, float x, float y, int color, boolean shadow)
return drawText(null, text, x, y, color, shadow);
}

float drawText(String text, float x, float y, int color, TextRenderer.TextType type);

float drawText(UMatrixStack matrixStack, String text, float x, float y, int color, boolean shadow);

int getStringWidth(String text);
Expand Down
30 changes: 2 additions & 28 deletions src/main/java/cc/polyfrost/oneconfig/renderer/TextRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,12 @@
import cc.polyfrost.oneconfig.libs.universal.UGraphics;
import cc.polyfrost.oneconfig.platform.Platform;

import java.util.regex.Pattern;

public class TextRenderer {
private static final Pattern regex = Pattern.compile("(?i)\u00A7[0-9a-f]");
private static boolean drawingBorder = false;

public static int drawBorderedText(String text, float x, float y, int color, int opacity) {
String noColors = regex.matcher(text).replaceAll("\u00A7r");
drawingBorder = true;
int yes = 0;
if (opacity / 4 > 3) {
for (int xOff = -2; xOff <= 2; xOff++) {
for (int yOff = -2; yOff <= 2; yOff++) {
if (xOff * xOff != yOff * yOff) {
yes += Platform.getGLPlatform().drawText(
noColors, (xOff / 2f) + x, (yOff / 2f) + y, (opacity / 4) << 24, false
);
}
}
}
}
yes += (int) Platform.getGLPlatform().drawText(text, x, y, color, false);
int yes = (int) Platform.getGLPlatform().drawText(text, x, y, (color & 0xFFFFFF) | (opacity << 24), TextType.FULL);
drawingBorder = false;
return yes;
}
Expand All @@ -62,17 +46,7 @@ public static float getStringWidth(String text) {
public static void drawScaledString(String text, float x, float y, int color, TextType type, float scale) {
UGraphics.GL.pushMatrix();
UGraphics.GL.scale(scale, scale, 1);
switch (type) {
case NONE:
Platform.getGLPlatform().drawText(text, x * (1 / scale), y * (1 / scale), color, false);
break;
case SHADOW:
Platform.getGLPlatform().drawText(text, x * (1 / scale), y * (1 / scale), color, true);
break;
case FULL:
drawBorderedText(text, x * (1 / scale), y * (1 / scale), color, 255);
break;
}
Platform.getGLPlatform().drawText(text, x * (1 / scale), y * (1 / scale), color, type);
UGraphics.GL.popMatrix();
}

Expand Down
1 change: 1 addition & 0 deletions versions/1.12.2-fabric/api/1.12.2-fabric.api
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class cc/polyfrost/oneconfig/platform/impl/GLPlatformImpl : cc/polyfrost/
public fun <init> ()V
public fun drawRect (FFFFI)V
public fun drawText (Lcc/polyfrost/oneconfig/libs/universal/UMatrixStack;Ljava/lang/String;FFIZ)F
public fun drawText (Ljava/lang/String;FFILcc/polyfrost/oneconfig/renderer/TextRenderer$TextType;)F
public fun enableStencil ()V
public fun getStringWidth (Ljava/lang/String;)I
}
Expand Down
1 change: 1 addition & 0 deletions versions/1.12.2-forge/api/1.12.2-forge.api
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class cc/polyfrost/oneconfig/platform/impl/GLPlatformImpl : cc/polyfrost/
public fun <init> ()V
public fun drawRect (FFFFI)V
public fun drawText (Lcc/polyfrost/oneconfig/libs/universal/UMatrixStack;Ljava/lang/String;FFIZ)F
public fun drawText (Ljava/lang/String;FFILcc/polyfrost/oneconfig/renderer/TextRenderer$TextType;)F
public fun enableStencil ()V
public fun getStringWidth (Ljava/lang/String;)I
}
Expand Down
1 change: 1 addition & 0 deletions versions/1.16.5-fabric/api/1.16.5-fabric.api
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class cc/polyfrost/oneconfig/platform/impl/GLPlatformImpl : cc/polyfrost/
public fun <init> ()V
public fun drawRect (FFFFI)V
public fun drawText (Lcc/polyfrost/oneconfig/libs/universal/UMatrixStack;Ljava/lang/String;FFIZ)F
public fun drawText (Ljava/lang/String;FFILcc/polyfrost/oneconfig/renderer/TextRenderer$TextType;)F
public fun enableStencil ()V
public fun getStringWidth (Ljava/lang/String;)I
}
Expand Down
1 change: 1 addition & 0 deletions versions/1.16.5-forge/api/1.16.5-forge.api
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class cc/polyfrost/oneconfig/platform/impl/GLPlatformImpl : cc/polyfrost/
public fun <init> ()V
public fun drawRect (FFFFI)V
public fun drawText (Lcc/polyfrost/oneconfig/libs/universal/UMatrixStack;Ljava/lang/String;FFIZ)F
public fun drawText (Ljava/lang/String;FFILcc/polyfrost/oneconfig/renderer/TextRenderer$TextType;)F
public fun enableStencil ()V
public fun getStringWidth (Ljava/lang/String;)I
}
Expand Down
1 change: 1 addition & 0 deletions versions/1.8.9-fabric/api/1.8.9-fabric.api
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class cc/polyfrost/oneconfig/platform/impl/GLPlatformImpl : cc/polyfrost/
public fun <init> ()V
public fun drawRect (FFFFI)V
public fun drawText (Lcc/polyfrost/oneconfig/libs/universal/UMatrixStack;Ljava/lang/String;FFIZ)F
public fun drawText (Ljava/lang/String;FFILcc/polyfrost/oneconfig/renderer/TextRenderer$TextType;)F
public fun enableStencil ()V
public fun getStringWidth (Ljava/lang/String;)I
}
Expand Down
1 change: 1 addition & 0 deletions versions/1.8.9-forge/api/1.8.9-forge.api
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class cc/polyfrost/oneconfig/platform/impl/GLPlatformImpl : cc/polyfrost/
public fun <init> ()V
public fun drawRect (FFFFI)V
public fun drawText (Lcc/polyfrost/oneconfig/libs/universal/UMatrixStack;Ljava/lang/String;FFIZ)F
public fun drawText (Ljava/lang/String;FFILcc/polyfrost/oneconfig/renderer/TextRenderer$TextType;)F
public fun enableStencil ()V
public fun getStringWidth (Ljava/lang/String;)I
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ public void init() {
LOGGER.error("Failed to handle Forge compatibility for {}", mod.getModId(), t);
}
}

cc.polyfrost.oneconfig.internal.renderer.BorderedTextHooks.INSTANCE.initialize();
//#else
//$$ try {
//$$ java.lang.reflect.Field mods = net.minecraftforge.fml.ModList.class.getDeclaredField("mods");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
/*
* This file is part of OneConfig.
* OneConfig - Next Generation Config Library for Minecraft: Java Edition
* Copyright (C) 2021~2023 Polyfrost.
* <https://polyfrost.cc> <https://github.com/Polyfrost/>
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* OneConfig is licensed under the terms of version 3 of the GNU Lesser
* General Public License as published by the Free Software Foundation, AND
* under the Additional Terms Applicable to OneConfig, as published by Polyfrost,
* either version 1.0 of the Additional Terms, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License. If not, see <https://www.gnu.org/licenses/>. You should
* have also received a copy of the Additional Terms Applicable
* to OneConfig, as published by Polyfrost. If not, see
* <https://polyfrost.cc/legal/oneconfig/additional-terms>
*/

//#if FORGE==1 && MC<=11202
package cc.polyfrost.oneconfig.internal.mixin;

import cc.polyfrost.oneconfig.internal.config.Preferences;
import cc.polyfrost.oneconfig.internal.renderer.BorderedTextHooks;
import cc.polyfrost.oneconfig.renderer.TextRenderer;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.util.ResourceLocation;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Constant;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.ModifyConstant;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(value = FontRenderer.class)
public class FontRendererMixin {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transfer all of this to a patcher font renderer mixin as well

@Shadow
protected float posX;

@Shadow
protected float posY;

@ModifyVariable(method = "drawString(Ljava/lang/String;FFIZ)I", at = @At(value = "HEAD"))
private boolean replaceShadow(boolean dropShadow) {
if (Preferences.optimizedFontRenderer && dropShadow) {
BorderedTextHooks.INSTANCE.setTextType(TextRenderer.TextType.SHADOW);
return false;
}
return dropShadow;
}

@Inject(method = "drawString(Ljava/lang/String;FFIZ)I", at = @At(value = "RETURN"), cancellable = true)
private void cachedShadow(String text, float x, float y, int color, boolean dropShadow, CallbackInfoReturnable<Integer> cir) {
if (Preferences.optimizedFontRenderer && dropShadow) {
BorderedTextHooks.INSTANCE.setTextType(TextRenderer.TextType.NONE);
cir.setReturnValue(cir.getReturnValue());
}
}

@ModifyConstant(method = "renderDefaultChar", constant = @Constant(floatValue = 128f))
private float asciiTextureSize(float constant) {
switch (BorderedTextHooks.INSTANCE.getTextType()) {
case SHADOW:
return 144f;
case FULL:
return 160f;
default:
return constant;
}
}

@Inject(method = "renderDefaultChar", at = @At("HEAD"))
private void asciiShift(int ch, boolean italic, CallbackInfoReturnable<Float> cir) {
if (BorderedTextHooks.INSTANCE.getTextType() == TextRenderer.TextType.FULL) {
posX -= 1;
posY -= 1;
}
}

@Inject(method = "renderDefaultChar", at = @At("RETURN"))
private void asciiUnshift(CallbackInfoReturnable<Float> cir) {
if (BorderedTextHooks.INSTANCE.getTextType() == TextRenderer.TextType.FULL) {
posX += 1;
posY += 1;
}
}

@ModifyConstant(method = "renderDefaultChar", constant = @Constant(intValue = 8))
private int asciiGlyphSize(int constant) {
switch (BorderedTextHooks.INSTANCE.getTextType()) {
case SHADOW:
return 9;
case FULL:
return 10;
default:
return constant;
}
}

@ModifyConstant(method = "renderDefaultChar", constant = @Constant(floatValue = 0.01f))
private float asciiGlyphWidth(float constant) {
switch (BorderedTextHooks.INSTANCE.getTextType()) {
case SHADOW:
return constant - 1.0f;
case FULL:
return constant - 4.0f;
default:
return constant;
}
}
@ModifyConstant(method = "renderDefaultChar", constant = @Constant(floatValue = 7.99f))
private float asciiPixelSize(float constant) {
switch (BorderedTextHooks.INSTANCE.getTextType()) {
case SHADOW:
return 8.99f;
case FULL:
return 9.99f;
default:
return constant;
}
}

@ModifyArg(method = "renderDefaultChar", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/FontRenderer;bindTexture(Lnet/minecraft/util/ResourceLocation;)V"))
private ResourceLocation asciiTexture(ResourceLocation location) {
switch (BorderedTextHooks.INSTANCE.getTextType()) {
case SHADOW:
return BorderedTextHooks.INSTANCE.getAsciiTexture().getShadowed().getLocation();
case FULL:
return BorderedTextHooks.INSTANCE.getAsciiTexture().getBordered().getLocation();
default:
return location;
}
}

@ModifyConstant(method = "renderUnicodeChar", constant = @Constant(floatValue = 256f))
private float unicodeTextureSize(float constant) {
switch (BorderedTextHooks.INSTANCE.getTextType()) {
case SHADOW:
return 272f;
case FULL:
return 320f;
default:
return constant;
}
}

@ModifyConstant(method = "renderUnicodeChar", constant = {@Constant(intValue = 16, ordinal = 1), @Constant(intValue = 16, ordinal = 3)})
private int unicodeGlyphSize(int constant) {
switch (BorderedTextHooks.INSTANCE.getTextType()) {
case SHADOW:
return 17;
case FULL:
return 20;
default:
return constant;
}
}

@ModifyConstant(method = "renderUnicodeChar", constant = @Constant(floatValue = 0.02f))
private float unicodeGlyphWidth(float constant) {
switch (BorderedTextHooks.INSTANCE.getTextType()) {
case SHADOW:
return constant - 1.0f;
case FULL:
return constant - 4.0f;
default:
return constant;
}
}

@ModifyConstant(method = "renderUnicodeChar", constant = @Constant(floatValue = 15.98F))
private float unicodeGlyphHeight(float constant) {
switch (BorderedTextHooks.INSTANCE.getTextType()) {
case SHADOW:
return 16.98f;
case FULL:
return 19.98f;
default:
return constant;
}
}

@ModifyConstant(method = "renderUnicodeChar", constant = @Constant(floatValue = 7.99f))
private float unicodePixelSize(float constant) {
switch (BorderedTextHooks.INSTANCE.getTextType()) {
case SHADOW:
return 8.49f;
case FULL:
return 9.99f;
default:
return constant;
}
}

@Inject(method = "getUnicodePageLocation", at = @At("HEAD"), cancellable = true)
private void unicodeTexture(int page, CallbackInfoReturnable<ResourceLocation> cir) {
switch (BorderedTextHooks.INSTANCE.getTextType()) {
case SHADOW:
cir.setReturnValue(BorderedTextHooks.INSTANCE.getUnicodeTexture()[page].getShadowed().getLocation());
break;
case FULL:
cir.setReturnValue(BorderedTextHooks.INSTANCE.getUnicodeTexture()[page].getBordered().getLocation());
break;
}
}


@Inject(method = "renderUnicodeChar", at = @At("HEAD"))
private void unicodeShift(char ch, boolean italic, CallbackInfoReturnable<Float> cir) {
if (BorderedTextHooks.INSTANCE.getTextType() == TextRenderer.TextType.FULL) {
posX -= 1f;
posY -= 1f;
}
}

@Inject(method = "renderUnicodeChar", at = @At("RETURN"))
private void unicodeUnshift(CallbackInfoReturnable<Float> cir) {
if (BorderedTextHooks.INSTANCE.getTextType() == TextRenderer.TextType.FULL) {
posX += 1f;
posY += 1f;
}
}
}
//#endif
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public List<String> getMixins() {
if (version == 10809 || version == 11202) {
// Patcher mixin
mixins.add("HudCachingMixin");
mixins.add("FontRendererMixin");
}
if (version >= 11600) {
mixins.add("ClientModLoaderMixin");
Expand Down
Loading
Loading