package com.mojang.blaze3d.platform; import java.io.EOFException; import java.nio.channels.ReadableByteChannel; import java.nio.ByteBuffer; import org.lwjgl.system.MemoryUtil; import java.nio.channels.Channels; import java.nio.channels.SeekableByteChannel; import java.io.FileInputStream; import java.nio.IntBuffer; import java.io.IOException; import org.lwjgl.stb.STBImage; import org.lwjgl.stb.STBIEOFCallbackI; import org.lwjgl.stb.STBISkipCallbackI; import org.lwjgl.stb.STBIReadCallbackI; import org.lwjgl.stb.STBIIOCallbacks; import org.lwjgl.stb.STBIEOFCallback; import org.lwjgl.stb.STBISkipCallback; import org.lwjgl.stb.STBIReadCallback; import org.lwjgl.system.MemoryStack; import java.io.InputStream; public class PngInfo { public final int width; public final int height; public PngInfo(final String string, final InputStream inputStream) throws IOException { try (final MemoryStack memoryStack4 = MemoryStack.stackPush(); final StbReader a6 = createCallbacks(inputStream); final STBIReadCallback sTBIReadCallback8 = STBIReadCallback.create(a6::read); final STBISkipCallback sTBISkipCallback10 = STBISkipCallback.create(a6::skip); final STBIEOFCallback sTBIEOFCallback12 = STBIEOFCallback.create(a6::eof)) { final STBIIOCallbacks sTBIIOCallbacks14 = STBIIOCallbacks.mallocStack(memoryStack4); sTBIIOCallbacks14.read((STBIReadCallbackI)sTBIReadCallback8); sTBIIOCallbacks14.skip((STBISkipCallbackI)sTBISkipCallback10); sTBIIOCallbacks14.eof((STBIEOFCallbackI)sTBIEOFCallback12); final IntBuffer intBuffer15 = memoryStack4.mallocInt(1); final IntBuffer intBuffer16 = memoryStack4.mallocInt(1); final IntBuffer intBuffer17 = memoryStack4.mallocInt(1); if (!STBImage.stbi_info_from_callbacks(sTBIIOCallbacks14, 0L, intBuffer15, intBuffer16, intBuffer17)) { throw new IOException("Could not read info from the PNG file " + string + " " + STBImage.stbi_failure_reason()); } this.width = intBuffer15.get(0); this.height = intBuffer16.get(0); } } private static StbReader createCallbacks(final InputStream inputStream) { if (inputStream instanceof FileInputStream) { return new StbReaderSeekableByteChannel((SeekableByteChannel)((FileInputStream)inputStream).getChannel()); } return new StbReaderBufferedChannel(Channels.newChannel(inputStream)); } abstract static class StbReader implements AutoCloseable { protected boolean closed; private StbReader() { } int read(final long long1, final long long2, final int integer) { try { return this.read(long2, integer); } catch (IOException iOException7) { this.closed = true; return 0; } } void skip(final long long1, final int integer) { try { this.skip(integer); } catch (IOException iOException5) { this.closed = true; } } int eof(final long long1) { return this.closed ? 1 : 0; } protected abstract int read(final long long1, final int integer) throws IOException; protected abstract void skip(final int integer) throws IOException; @Override public abstract void close() throws IOException; } static class StbReaderSeekableByteChannel extends StbReader { private final SeekableByteChannel channel; private StbReaderSeekableByteChannel(final SeekableByteChannel seekableByteChannel) { this.channel = seekableByteChannel; } public int read(final long long1, final int integer) throws IOException { final ByteBuffer byteBuffer5 = MemoryUtil.memByteBuffer(long1, integer); return this.channel.read(byteBuffer5); } public void skip(final int integer) throws IOException { this.channel.position(this.channel.position() + integer); } public int eof(final long long1) { return (super.eof(long1) != 0 && this.channel.isOpen()) ? 1 : 0; } @Override public void close() throws IOException { this.channel.close(); } } static class StbReaderBufferedChannel extends StbReader { private final ReadableByteChannel channel; private long readBufferAddress; private int bufferSize; private int read; private int consumed; private StbReaderBufferedChannel(final ReadableByteChannel readableByteChannel) { this.readBufferAddress = MemoryUtil.nmemAlloc(128L); this.bufferSize = 128; this.channel = readableByteChannel; } private void fillReadBuffer(final int integer) throws IOException { ByteBuffer byteBuffer3 = MemoryUtil.memByteBuffer(this.readBufferAddress, this.bufferSize); if (integer + this.consumed > this.bufferSize) { this.bufferSize = integer + this.consumed; byteBuffer3 = MemoryUtil.memRealloc(byteBuffer3, this.bufferSize); this.readBufferAddress = MemoryUtil.memAddress(byteBuffer3); } byteBuffer3.position(this.read); while (integer + this.consumed > this.read) { try { final int integer2 = this.channel.read(byteBuffer3); if (integer2 == -1) { break; } continue; } finally { this.read = byteBuffer3.position(); } } } public int read(final long long1, int integer) throws IOException { this.fillReadBuffer(integer); if (integer + this.consumed > this.read) { integer = this.read - this.consumed; } MemoryUtil.memCopy(this.readBufferAddress + this.consumed, long1, (long)integer); this.consumed += integer; return integer; } public void skip(final int integer) throws IOException { if (integer > 0) { this.fillReadBuffer(integer); if (integer + this.consumed > this.read) { throw new EOFException("Can't skip past the EOF."); } } if (this.consumed + integer < 0) { throw new IOException("Can't seek before the beginning: " + (this.consumed + integer)); } this.consumed += integer; } @Override public void close() throws IOException { MemoryUtil.nmemFree(this.readBufferAddress); this.channel.close(); } } }