From abf5c4b3de56dc444ccdef095db5a896e45f49f4 Mon Sep 17 00:00:00 2001 From: cvrunmin Date: Thu, 20 Jul 2023 21:58:41 +0800 Subject: [PATCH] use vanilla font system for terminal --- .../client/render/PrintoutRenderer.java | 4 +- .../render/text/DynamicFontTexture.java | 15 ++-- .../client/render/text/TerminalFont.java | 83 +++++------------- .../computercraft/font/terminal_font.json | 45 ++++++++++ .../textures/font/terminal_ansi.png | Bin 0 -> 1697 bytes 5 files changed, 79 insertions(+), 68 deletions(-) create mode 100644 projects/common/src/main/resources/assets/computercraft/font/terminal_font.json create mode 100644 projects/common/src/main/resources/assets/computercraft/textures/font/terminal_ansi.png diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutRenderer.java index e4aa3a1b9..696844393 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutRenderer.java @@ -59,7 +59,7 @@ public final class PrintoutRenderer { } public static void drawText(PoseStack transform, MultiBufferSource bufferSource, int x, int y, int start, int light, TextBuffer[] text, TextBuffer[] colours) { - var buffer = bufferSource.getBuffer(RenderTypes.PRINTOUT_TEXT); + var buffer = bufferSource.getBuffer(RenderTypes.PRINTOUT_FULLTEXT); var emitter = FixedWidthFontRenderer.toVertexConsumer(transform, buffer); for (var line = 0; line < LINES_PER_PAGE && line < text.length; line++) { FixedWidthFontRenderer.drawString(emitter, @@ -70,7 +70,7 @@ public final class PrintoutRenderer { } public static void drawText(PoseStack transform, MultiBufferSource bufferSource, int x, int y, int start, int light, String[] text, String[] colours) { - var buffer = bufferSource.getBuffer(RenderTypes.PRINTOUT_TEXT); + var buffer = bufferSource.getBuffer(RenderTypes.PRINTOUT_FULLTEXT); var emitter = FixedWidthFontRenderer.toVertexConsumer(transform, buffer); for (var line = 0; line < LINES_PER_PAGE && line < text.length; line++) { FixedWidthFontRenderer.drawString(emitter, diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/text/DynamicFontTexture.java b/projects/common/src/client/java/dan200/computercraft/client/render/text/DynamicFontTexture.java index 3115919ce..99ec86172 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/text/DynamicFontTexture.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/text/DynamicFontTexture.java @@ -29,7 +29,10 @@ import java.util.function.Function; public class DynamicFontTexture extends AbstractTexture { public static final ResourceLocation DEFAULT_NAME = new ResourceLocation(ComputerCraftAPI.MOD_ID, "dyn_term_font"); - private static final int MINIMUM_SIZE = 512; + + public static final ResourceLocation TERMINAL_FONT_DEFINATION = new ResourceLocation(ComputerCraftAPI.MOD_ID, "terminal_font"); + + private static final int MINIMUM_SIZE = 256; private int currentSize; private TextureSlotNode rootNode; @@ -97,7 +100,7 @@ public class DynamicFontTexture extends AbstractTexture { public RegisteredGlyph getGlyph(int codepoint){ return glyphs.computeIfAbsent(codepoint, cp -> { - var fontSet = Minecraft.getInstance().font.getFontSet(Minecraft.UNIFORM_FONT); + var fontSet = Minecraft.getInstance().font.getFontSet(TERMINAL_FONT_DEFINATION); var glyphInfo = fontSet.getGlyphInfo(cp, false); if(glyphInfo != SpecialGlyphs.MISSING){ var glyph = registerGlyph(glyphInfo); @@ -118,9 +121,7 @@ public class DynamicFontTexture extends AbstractTexture { private RegisteredGlyph registerGlyph(GlyphInfo glyphInfo) { var regGlyphWrapper = new RegisteredGlyph[]{ null }; glyphInfo.bake(sheetGlyphInfo -> { - var offsetX = ((int) glyphInfo.getAdvance()); - offsetX = offsetX + sheetGlyphInfo.getPixelWidth() <= 16 ? offsetX : 0; - var wrapper = new SheetGlyphInfoWrapper(sheetGlyphInfo, Optional.of(offsetX)); + var wrapper = new SheetGlyphInfoWrapper(sheetGlyphInfo, Optional.empty()); var assignedNode = rootNode.insert(wrapper); if (assignedNode == null) { resize(currentSize * 2); @@ -130,8 +131,8 @@ public class DynamicFontTexture extends AbstractTexture { return null; } bind(); - sheetGlyphInfo.upload(assignedNode.x + offsetX / 2, assignedNode.y); - regGlyphWrapper[0] = new RegisteredGlyph(assignedNode.x, assignedNode.y, assignedNode.x + sheetGlyphInfo.getPixelWidth() + offsetX, assignedNode.y + sheetGlyphInfo.getPixelHeight()); + sheetGlyphInfo.upload(assignedNode.x, assignedNode.y); + regGlyphWrapper[0] = new RegisteredGlyph(assignedNode.x, assignedNode.y, assignedNode.x + sheetGlyphInfo.getPixelWidth(), assignedNode.y + sheetGlyphInfo.getPixelHeight()); return null; }); return regGlyphWrapper[0]; diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/text/TerminalFont.java b/projects/common/src/client/java/dan200/computercraft/client/render/text/TerminalFont.java index 77b00b69c..376989a59 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/text/TerminalFont.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/text/TerminalFont.java @@ -1,25 +1,16 @@ package dan200.computercraft.client.render.text; -import com.mojang.blaze3d.font.GlyphInfo; -import com.mojang.blaze3d.font.SheetGlyphInfo; -import com.mojang.blaze3d.platform.NativeImage; import dan200.computercraft.core.terminal.TextBuffer; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.font.glyphs.BakedGlyph; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ReloadableResourceManager; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimplePreparableReloadListener; +import net.minecraft.util.profiling.ProfilerFiller; import org.joml.Vector4f; import javax.annotation.Nullable; -import java.io.IOException; -import java.util.function.Function; public class TerminalFont { - - public static final ResourceLocation ANSI_TERM_FONT = new ResourceLocation("computercraft", "textures/gui/term_font.png"); - - public static final int FONT_HEIGHT = 9; - public static final int FONT_WIDTH = 6; - static final float WIDTH = 256.0f; private DynamicFontTexture fullTexture; @Nullable @@ -33,20 +24,27 @@ public class TerminalFont { } private TerminalFont(){ - this.fullTexture = new DynamicFontTexture(512); - Minecraft.getInstance().getTextureManager().register(DynamicFontTexture.DEFAULT_NAME, this.fullTexture); - try (var stream = Minecraft.getInstance().getResourceManager().open(ANSI_TERM_FONT)){ - var image = NativeImage.read(stream); - var scale = image.getWidth() / WIDTH; - for (int i = 1; i < 256; i++) { - var column = i % 16; - var row = i / 16; - var xStart = 1 + column * (FONT_WIDTH + 2); - var yStart = 1 + row * (FONT_HEIGHT + 2); - fullTexture.registeredGlyph(i, new ANSITerminalGlyphInfo(image, (int) (xStart * scale), (int) (yStart * scale), (int) (FONT_WIDTH * scale), (int) (FONT_HEIGHT * scale))); + prepareFontTexture(); + ((ReloadableResourceManager) Minecraft.getInstance().getResourceManager()).registerReloadListener(new SimplePreparableReloadListener() { + @Override + protected Void prepare(ResourceManager resourceManager, ProfilerFiller profilerFiller) { + return null; } - } catch (IOException e) { - throw new RuntimeException(e); + + @Override + protected void apply(Void unused, ResourceManager resourceManager, ProfilerFiller profilerFiller) { + TerminalFont.this.fullTexture.close(); + prepareFontTexture(); + } + }); + } + + private void prepareFontTexture() { + this.fullTexture = new DynamicFontTexture(256); + Minecraft.getInstance().getTextureManager().register(DynamicFontTexture.DEFAULT_NAME, this.fullTexture); + // preload codepoint 0x01-0xff + for (int i = 1; i < 256; i++) { + this.fullTexture.getGlyph(i); } } @@ -81,37 +79,4 @@ public class TerminalFont { preloadCharacterFont(textBuffer); } } - - record ANSITerminalGlyphInfo(NativeImage image, int offsetX, int offsetY, int width, int height) implements GlyphInfo{ - - public float getAdvance() { - return 0; - } - - public BakedGlyph bake(Function function) { - return function.apply(new SheetGlyphInfo() { - @Override - public int getPixelWidth() { - return ANSITerminalGlyphInfo.this.width; - } - @Override - public int getPixelHeight() { - return ANSITerminalGlyphInfo.this.height; - } - @Override - public void upload(int xOffset, int yOffset) { - ANSITerminalGlyphInfo.this.image.upload(0, xOffset, yOffset, ANSITerminalGlyphInfo.this.offsetX, ANSITerminalGlyphInfo.this.offsetY, width, height, false, false); - } - @Override - public boolean isColored() { - return true; - } - @Override - public float getOversample() { - return 1; - } - }); - } - } - } diff --git a/projects/common/src/main/resources/assets/computercraft/font/terminal_font.json b/projects/common/src/main/resources/assets/computercraft/font/terminal_font.json new file mode 100644 index 000000000..c45f0c9ee --- /dev/null +++ b/projects/common/src/main/resources/assets/computercraft/font/terminal_font.json @@ -0,0 +1,45 @@ +{ + "providers": [ + { + "type": "bitmap", + "file": "computercraft:font/terminal_ansi.png", + "ascent": 8, + "height": 9, + "chars": [ + "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u000a\u000b\u000c\u000d\u000e\u000f\u0000\u0000\u0000\u0000\u0000", + "\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f\u0000\u0000\u0000\u0000\u0000", + "\u0020\u0021\u0022\u0023\u0024\u0025\u0026\u0027\u0028\u0029\u002a\u002b\u002c\u002d\u002e\u002f\u0000\u0000\u0000\u0000\u0000", + "\u0030\u0031\u0032\u0033\u0034\u0035\u0036\u0037\u0038\u0039\u003a\u003b\u003c\u003d\u003e\u003f\u0000\u0000\u0000\u0000\u0000", + "\u0040\u0041\u0042\u0043\u0044\u0045\u0046\u0047\u0048\u0049\u004a\u004b\u004c\u004d\u004e\u004f\u0000\u0000\u0000\u0000\u0000", + "\u0050\u0051\u0052\u0053\u0054\u0055\u0056\u0057\u0058\u0059\u005a\u005b\u005c\u005d\u005e\u005f\u0000\u0000\u0000\u0000\u0000", + "\u0060\u0061\u0062\u0063\u0064\u0065\u0066\u0067\u0068\u0069\u006a\u006b\u006c\u006d\u006e\u006f\u0000\u0000\u0000\u0000\u0000", + "\u0070\u0071\u0072\u0073\u0074\u0075\u0076\u0077\u0078\u0079\u007a\u007b\u007c\u007d\u007e\u007f\u0000\u0000\u0000\u0000\u0000", + "\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0000\u0000\u0000\u0000\u0000", + "\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u0000\u0000\u0000\u0000\u0000", + "\u00a0\u00a1\u00a2\u00a3\u00a4\u00a5\u00a6\u00a7\u00a8\u00a9\u00aa\u00ab\u00ac\u00ad\u00ae\u00af\u0000\u0000\u0000\u0000\u0000", + "\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u00ba\u00bb\u00bc\u00bd\u00be\u00bf\u0000\u0000\u0000\u0000\u0000", + "\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf\u0000\u0000\u0000\u0000\u0000", + "\u00d0\u00d1\u00d2\u00d3\u00d4\u00d5\u00d6\u00d7\u00d8\u00d9\u00da\u00db\u00dc\u00dd\u00de\u00df\u0000\u0000\u0000\u0000\u0000", + "\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u00e6\u00e7\u00e8\u00e9\u00ea\u00eb\u00ec\u00ed\u00ee\u00ef\u0000\u0000\u0000\u0000\u0000", + "\u00f0\u00f1\u00f2\u00f3\u00f4\u00f5\u00f6\u00f7\u00f8\u00f9\u00fa\u00fb\u00fc\u00fd\u00fe\u00ff\u0000\u0000\u0000\u0000\u0000", + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + ] + }, + { + "type": "legacy_unicode", + "sizes": "minecraft:font/glyph_sizes.bin", + "template": "minecraft:font/unicode_page_%s.png" + } + ] +} diff --git a/projects/common/src/main/resources/assets/computercraft/textures/font/terminal_ansi.png b/projects/common/src/main/resources/assets/computercraft/textures/font/terminal_ansi.png new file mode 100644 index 0000000000000000000000000000000000000000..12fe0e947ab7760ac34d90999a0cb74028e883fd GIT binary patch literal 1697 zcmV;S244AzP)j2VQ7>2>6E(fp&c*+Be_xHCup7pKkkn`mqBi^HejP3YI1P0G%Pg$t5 z* zpj=LdbC4YbjVZHc0XQjDSm1b2Iqq?q-id+?nVh@D5`gz_&>qf$1U$l=lP-C_7{D|6 zqWdFdJtS^}RSTeX4WQY%>8uN;ol5}7_~W2+PK1b2xQ>dp1)yJ~OAYU;Qww0%OVE?y z;SzSl%@H_R^~?~+2#`Y%Mu7%^ck=+gm56ML=?Rju9!*$WR@S7FOUK73OU^lxk@6{+ zb7Hs5`2oQByn#YY3&#-vl3_?wG3y?o=p{W1VrZ10CwVoeh@^`1#0gAV3KYT4{pHwe zAMg#%V6_jdXd#LMJqgu9-H8;30}+$uYk2@SefK&dlGT7l|Mu$xJWN`#*mLHx9F}B^ z5Ka|(+&hrL-3{cb2OIh@@ECWz?jW5Z)5>Aqe=q6SpcpNGBiUmjnQ-)RwPyw)I{#Pg> zhgUABUVpMATQW{FD}>0c3SI)hR0$43NMY}^(}@TyxyPDtRH{P4vnbssH6gfk7M3ZH z9X-~WktQ5hi?DNlDa)Z!jxWjNa)w$+*&G60qc%l3xJ*cuG#v%2L$FQ>8L@-46_b~% zok=q4;uNw);i}^WV8aJgW>y!s`?yJ?091+QI{*|96cPPp0MU)E+82Pd55N_QT$Th+ z946gFTU9bNu1M3|AC4-;wq|uLz`crUEf{PW$mR!_WteQ1af}UGQMZ$oCTd8spd?or zP5|IZA9q?pFV?}%CZC^T-vYLkP4>X++L&6rFh%?gA8@+sn`xTxdN0p8p;r-ohg$iF z<$GOfaazM>Ei0;$u&{0f1T7)l8HNUTp#`?LZh6(LX|4n8b0O@~(d|yM_YL_W;5A}X zOn(+8-~n*f(RSPUA`A4ojFKzz(_`qd#Kjng0|SU;6ZsxwGB~|v)LUyY;10ILRAuQnKl)@^E1tdP1}oUiejh-_0#dGAZh;(t{%Y3MK5(~s`ItT;meK(!$q5S&AuTs> zS5nRg=%of)u44Cda~vXpwzX!2uwAXU4tlG@YH1rSIXMx11G89&*2n!WBdl5ga{yvO zI0o4kbTO=uIJ1vhU#C%E$33K!$vIF1dm|6vYltYJh`jpII~9=u`))-*;v( zRoSjR>p%hk0swSH3RMhaI+l>KmjNKAHV}eL