minecraft-source/src/com/mojang/blaze3d/platform/PngInfo.java

183 lines
7.0 KiB
Java

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();
}
}
}