package com.mojang.blaze3d.font;

import com.mojang.blaze3d.platform.NativeImage;
import java.util.function.Supplier;
import it.unimi.dsi.fastutil.ints.IntCollection;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import java.util.stream.IntStream;
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.ints.IntArraySet;
import it.unimi.dsi.fastutil.ints.IntSet;
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 IntSet 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 = (IntSet)new IntArraySet();
        this.fontMemory = byteBuffer;
        this.font = sTBTTFontinfo;
        this.oversample = float4;
        string.codePoints().forEach(this.skip::add);
        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 int integer) {
        if (this.skip.contains(integer)) {
            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 integer2 = STBTruetype.stbtt_FindGlyphIndex(this.font, integer);
            if (integer2 == 0) {
                return null;
            }
            STBTruetype.stbtt_GetGlyphBitmapBoxSubpixel(this.font, integer2, this.pointScale, this.pointScale, this.shiftX, this.shiftY, intBuffer5, intBuffer6, intBuffer7, intBuffer8);
            final int integer3 = intBuffer7.get(0) - intBuffer5.get(0);
            final int integer4 = intBuffer8.get(0) - intBuffer6.get(0);
            if (integer3 == 0 || integer4 == 0) {
                return null;
            }
            final IntBuffer intBuffer9 = memoryStack3.mallocInt(1);
            final IntBuffer intBuffer10 = memoryStack3.mallocInt(1);
            STBTruetype.stbtt_GetGlyphHMetrics(this.font, integer2, 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, integer2);
        }
    }
    
    @Override
    public void close() {
        this.font.free();
        MemoryUtil.memFree((Buffer)this.fontMemory);
    }
    
    @Override
    public IntSet getSupportedGlyphs() {
        return IntStream.range(0, 65535).filter(integer -> !this.skip.contains(integer)).<IntSet>collect((Supplier<IntSet>)IntOpenHashSet::new, IntCollection::add, IntCollection::addAll);
    }
    
    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 dgs4 = new NativeImage(NativeImage.Format.LUMINANCE, this.width, this.height, false);
            dgs4.copyFromFont(TrueTypeGlyphProvider.this.font, this.index, this.width, this.height, TrueTypeGlyphProvider.this.pointScale, TrueTypeGlyphProvider.this.pointScale, TrueTypeGlyphProvider.this.shiftX, TrueTypeGlyphProvider.this.shiftY, 0, 0);
            dgs4.upload(0, integer1, integer2, 0, 0, this.width, this.height, false, true);
        }
        
        @Override
        public boolean isColored() {
            return false;
        }
    }
}
