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

Extend range of characters rendered by the custom font renderer #4362

Merged
merged 3 commits into from
Jan 29, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,25 @@

package meteordevelopment.meteorclient.renderer.text;

import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import meteordevelopment.meteorclient.renderer.Mesh;
import meteordevelopment.meteorclient.utils.render.ByteTexture;
import meteordevelopment.meteorclient.utils.render.color.Color;
import net.minecraft.client.texture.AbstractTexture;
import org.lwjgl.BufferUtils;
import org.lwjgl.stb.STBTTFontinfo;
import org.lwjgl.stb.STBTTPackContext;
import org.lwjgl.stb.STBTTPackedchar;
import org.lwjgl.stb.STBTruetype;
import org.lwjgl.stb.*;
import org.lwjgl.system.MemoryStack;

import java.nio.ByteBuffer;
import java.nio.IntBuffer;

public class Font {
public AbstractTexture texture;

private final int height;
private final float scale;
private final float ascent;
private final CharData[] charData;
private final Int2ObjectOpenHashMap<CharData> charMap = new Int2ObjectOpenHashMap<>();
private final static int size = 2048;

public Font(ByteBuffer buffer, int height) {
this.height = height;
Expand All @@ -34,20 +32,37 @@ public Font(ByteBuffer buffer, int height) {
STBTTFontinfo fontInfo = STBTTFontinfo.create();
STBTruetype.stbtt_InitFont(fontInfo, buffer);

// Allocate STBTTPackedchar buffer
charData = new CharData[128];
STBTTPackedchar.Buffer cdata = STBTTPackedchar.create(charData.length);
ByteBuffer bitmap = BufferUtils.createByteBuffer(2048 * 2048);

// Create font texture
// Allocate buffers
ByteBuffer bitmap = BufferUtils.createByteBuffer(size * size);
STBTTPackedchar.Buffer[] cdata = {
STBTTPackedchar.create(95), // Basic Latin
STBTTPackedchar.create(96), // Latin 1 Supplement
STBTTPackedchar.create(128), // Latin Extended-A
STBTTPackedchar.create(144), // Greek and Coptic
STBTTPackedchar.create(256), // Cyrillic
STBTTPackedchar.create(1) // infinity symbol
};

// create and initialise packing context
STBTTPackContext packContext = STBTTPackContext.create();
STBTruetype.stbtt_PackBegin(packContext, bitmap, 2048, 2048, 0, 1);
STBTruetype.stbtt_PackSetOversampling(packContext, 2, 2);
STBTruetype.stbtt_PackFontRange(packContext, buffer, 0, height, 32, cdata);
STBTruetype.stbtt_PackBegin(packContext, bitmap, size, size, 0 ,1);

// create the pack range, populate with the specific packing ranges
STBTTPackRange.Buffer packRange = STBTTPackRange.create(cdata.length);
packRange.put(STBTTPackRange.create().set(height, 32, null, 95, cdata[0], (byte) 2, (byte) 2));
packRange.put(STBTTPackRange.create().set(height, 160, null, 96, cdata[1], (byte) 2, (byte) 2));
packRange.put(STBTTPackRange.create().set(height, 256, null, 128, cdata[2], (byte) 2, (byte) 2));
packRange.put(STBTTPackRange.create().set(height, 880, null, 144, cdata[3], (byte) 2, (byte) 2));
packRange.put(STBTTPackRange.create().set(height, 1024, null, 256, cdata[4], (byte) 2, (byte) 2));
packRange.put(STBTTPackRange.create().set(height, 8734, null, 1, cdata[5], (byte) 2, (byte) 2)); // lol
packRange.flip();

// write and finish
STBTruetype.stbtt_PackFontRanges(packContext, buffer, 0, packRange);
STBTruetype.stbtt_PackEnd(packContext);

// Create texture object and get font scale
texture = new ByteTexture(2048, 2048, bitmap, ByteTexture.Format.A, ByteTexture.Filter.Linear, ByteTexture.Filter.Linear);
texture = new ByteTexture(size, size, bitmap, ByteTexture.Format.A, ByteTexture.Filter.Linear, ByteTexture.Filter.Linear);
scale = STBTruetype.stbtt_ScaleForPixelHeight(fontInfo, height);

// Get font vertical ascent
Expand All @@ -57,14 +72,17 @@ public Font(ByteBuffer buffer, int height) {
this.ascent = ascent.get(0);
}

// Populate charData array
for (int i = 0; i < charData.length; i++) {
STBTTPackedchar packedChar = cdata.get(i);
for (int i = 0; i < cdata.length; i++) {
STBTTPackedchar.Buffer cbuf = cdata[i];
int offset = packRange.get(i).first_unicode_codepoint_in_range();

float ipw = 1f / 2048;
float iph = 1f / 2048;
for (int j = 0; j < cbuf.capacity(); j++) {
STBTTPackedchar packedChar = cbuf.get(j);

charData[i] = new CharData(
float ipw = 1f / size; // pixel width and height
float iph = 1f / size;

charMap.put(j + offset, new CharData(
packedChar.xoff(),
packedChar.yoff(),
packedChar.xoff2(),
Expand All @@ -74,7 +92,8 @@ public Font(ByteBuffer buffer, int height) {
packedChar.x1() * ipw,
packedChar.y1() * iph,
packedChar.xadvance()
);
));
}
}
}

Expand All @@ -83,8 +102,8 @@ public double getWidth(String string, int length) {

for (int i = 0; i < length; i++) {
int cp = string.charAt(i);
if (cp < 32 || cp > 128) cp = 32;
CharData c = charData[cp - 32];
CharData c = charMap.get(cp);
if (c == null) c = charMap.get(32);

width += c.xAdvance;
}
Expand All @@ -101,8 +120,8 @@ public double render(Mesh mesh, String string, double x, double y, Color color,

for (int i = 0; i < string.length(); i++) {
int cp = string.charAt(i);
if (cp < 32 || cp > 128) cp = 32;
CharData c = charData[cp - 32];
CharData c = charMap.get(cp);
if (c == null) c = charMap.get(32);

mesh.quad(
mesh.vec2(x + c.x0 * scale, y + c.y0 * scale).vec2(c.u0, c.v0).color(color).next(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import meteordevelopment.meteorclient.utils.render.color.SettingColor;
import net.minecraft.entity.effect.StatusEffect;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.util.StringHelper;
import net.minecraft.entity.effect.StatusEffectUtil;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -241,7 +241,7 @@ public void render(HudRenderer renderer) {
}

private String getString(StatusEffectInstance statusEffectInstance) {
return String.format("%s %d (%s)", Names.get(statusEffectInstance.getEffectType()), statusEffectInstance.getAmplifier() + 1, statusEffectInstance.isInfinite() ? "inf" : StringHelper.formatTicks(statusEffectInstance.getDuration(), mc.world.getTickManager().getTickRate())); //todo remove "inf" when font rendering can use symbols
return String.format("%s %d (%s)", Names.get(statusEffectInstance.getEffectType()), statusEffectInstance.getAmplifier() + 1, StatusEffectUtil.getDurationText(statusEffectInstance, 1, mc.world.getTickManager().getTickRate()).getString());
}

private double getScale() {
Expand Down
Loading