package com.mojang.blaze3d.font; import com.mojang.blaze3d.platform.NativeImage; import java.nio.Buffer; import org.lwjgl.system.MemoryUtil; import javax.annotation.Nullable; import java.nio.IntBuffer; import org.lwjgl.system.MemoryStack; import org.lwjgl.stb.STBTruetype; import it.unimi.dsi.fastutil.chars.CharArraySet; import it.unimi.dsi.fastutil.chars.CharSet; import org.lwjgl.stb.STBTTFontinfo; import java.nio.ByteBuffer; public class TrueTypeGlyphProvider implements GlyphProvider { private final ByteBuffer fontMemory; private final STBTTFontinfo font; private final float oversample; private final CharSet skip; private final float shiftX; private final float shiftY; private final float pointScale; private final float ascent; public TrueTypeGlyphProvider(final ByteBuffer byteBuffer, final STBTTFontinfo sTBTTFontinfo, final float float3, final float float4, final float float5, final float float6, final String string) { this.skip = (CharSet)new CharArraySet(); this.fontMemory = byteBuffer; this.font = sTBTTFontinfo; this.oversample = float4; string.chars().forEach(integer -> this.skip.add((char)(integer & 0xFFFF))); this.shiftX = float5 * float4; this.shiftY = float6 * float4; this.pointScale = STBTruetype.stbtt_ScaleForPixelHeight(sTBTTFontinfo, float3 * float4); try (final MemoryStack memoryStack9 = MemoryStack.stackPush()) { final IntBuffer intBuffer11 = memoryStack9.mallocInt(1); final IntBuffer intBuffer12 = memoryStack9.mallocInt(1); final IntBuffer intBuffer13 = memoryStack9.mallocInt(1); STBTruetype.stbtt_GetFontVMetrics(sTBTTFontinfo, intBuffer11, intBuffer12, intBuffer13); this.ascent = intBuffer11.get(0) * this.pointScale; } } @Nullable @Override public Glyph getGlyph(final char character) { if (this.skip.contains(character)) { return null; } try (final MemoryStack memoryStack3 = MemoryStack.stackPush()) { final IntBuffer intBuffer5 = memoryStack3.mallocInt(1); final IntBuffer intBuffer6 = memoryStack3.mallocInt(1); final IntBuffer intBuffer7 = memoryStack3.mallocInt(1); final IntBuffer intBuffer8 = memoryStack3.mallocInt(1); final int integer9 = STBTruetype.stbtt_FindGlyphIndex(this.font, (int)character); if (integer9 == 0) { return null; } STBTruetype.stbtt_GetGlyphBitmapBoxSubpixel(this.font, integer9, this.pointScale, this.pointScale, this.shiftX, this.shiftY, intBuffer5, intBuffer6, intBuffer7, intBuffer8); final int integer10 = intBuffer7.get(0) - intBuffer5.get(0); final int integer11 = intBuffer8.get(0) - intBuffer6.get(0); if (integer10 == 0 || integer11 == 0) { return null; } final IntBuffer intBuffer9 = memoryStack3.mallocInt(1); final IntBuffer intBuffer10 = memoryStack3.mallocInt(1); STBTruetype.stbtt_GetGlyphHMetrics(this.font, integer9, intBuffer9, intBuffer10); return new Glyph(intBuffer5.get(0), intBuffer7.get(0), -intBuffer6.get(0), -intBuffer8.get(0), intBuffer9.get(0) * this.pointScale, intBuffer10.get(0) * this.pointScale, integer9); } } @Override public void close() { this.font.free(); MemoryUtil.memFree((Buffer)this.fontMemory); } class Glyph implements RawGlyph { private final int width; private final int height; private final float bearingX; private final float bearingY; private final float advance; private final int index; private Glyph(final int integer2, final int integer3, final int integer4, final int integer5, final float float6, final float float7, final int integer8) { this.width = integer3 - integer2; this.height = integer4 - integer5; this.advance = float6 / TrueTypeGlyphProvider.this.oversample; this.bearingX = (float7 + integer2 + TrueTypeGlyphProvider.this.shiftX) / TrueTypeGlyphProvider.this.oversample; this.bearingY = (TrueTypeGlyphProvider.this.ascent - integer4 + TrueTypeGlyphProvider.this.shiftY) / TrueTypeGlyphProvider.this.oversample; this.index = integer8; } @Override public int getPixelWidth() { return this.width; } @Override public int getPixelHeight() { return this.height; } @Override public float getOversample() { return TrueTypeGlyphProvider.this.oversample; } @Override public float getAdvance() { return this.advance; } @Override public float getBearingX() { return this.bearingX; } @Override public float getBearingY() { return this.bearingY; } @Override public void upload(final int integer1, final int integer2) { final NativeImage cxr4 = new NativeImage(NativeImage.Format.LUMINANCE, this.width, this.height, false); cxr4.copyFromFont(TrueTypeGlyphProvider.this.font, this.index, this.width, this.height, TrueTypeGlyphProvider.this.pointScale, TrueTypeGlyphProvider.this.pointScale, TrueTypeGlyphProvider.this.shiftX, TrueTypeGlyphProvider.this.shiftY, 0, 0); cxr4.upload(0, integer1, integer2, 0, 0, this.width, this.height, false, true); } @Override public boolean isColored() { return false; } } }