package com.intellij.flex.uiDesigner.abc; import com.intellij.openapi.util.io.FileUtil; import java.io.*; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.zip.DataFormatException; import java.util.zip.Inflater; import java.util.zip.ZipException; abstract class SwfTranscoder extends AbcEncoder { private static final ThreadLocal<Inflater> INFLATER = new ThreadLocal<Inflater>() { @Override protected Inflater initialValue() { return new Inflater(); } }; protected static final int PARTIAL_HEADER_LENGTH = 8; private final byte[] partialHeader = new byte[PARTIAL_HEADER_LENGTH]; protected FileOutputStream readSourceAndCreateFileOut(InputStream inputStream, long inputLength, File outFile) throws IOException { readSource(inputStream, inputLength); return new FileOutputStream(outFile); } // in will be closed protected void readSource(InputStream in, long inputLength) throws IOException { final int uncompressedBodyLength; final boolean compressed; byte[] data; try { int n = in.read(partialHeader); assert n == PARTIAL_HEADER_LENGTH; uncompressedBodyLength = (partialHeader[4] & 0xFF | (partialHeader[5] & 0xFF) << 8 | (partialHeader[6] & 0xFF) << 16 | partialHeader[7] << 24) - PARTIAL_HEADER_LENGTH; compressed = partialHeader[0] == 0x43; data = FileUtil.loadBytes(in, compressed ? (int)inputLength - PARTIAL_HEADER_LENGTH : uncompressedBodyLength); } finally { in.close(); } if (compressed) { final Inflater inflater = INFLATER.get(); try { inflater.setInput(data); byte[] uncompressedData = new byte[uncompressedBodyLength]; try { inflater.inflate(uncompressedData); } catch (DataFormatException e) { throw new ZipException(e.getMessage() != null ? e.getMessage() : "Invalid ZLIB data format"); } data = uncompressedData; } finally { inflater.reset(); } } buffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN); readFrameSizeFrameRateAndFrameCount(data[0]); } protected void readFrameSizeFrameRateAndFrameCount(byte b) throws IOException { // skip FrameSize, FrameRate, FrameCount buffer.position((int)Math.ceil((float)(5 + ((b & 0xFF) >> -(5 - 8)) * 4) / 8) + 2 + 2); } protected void writePartialHeader(int fileLength) { partialHeader[0] = 0x46; // write as uncompressed buffer.put(partialHeader, 0, 4); buffer.putInt(fileLength); } protected void writePartialHeader(OutputStream out, int fileLength) throws IOException { partialHeader[0] = 0x46; // write as uncompressed // fileLength int as little endian partialHeader[4] = (byte)(0xff & fileLength); partialHeader[5] = (byte)(0xff & fileLength >> 8); partialHeader[6] = (byte)(0xff & fileLength >> 16); partialHeader[7] = (byte)(0xff & fileLength >> 24); out.write(partialHeader); } protected static class TagPositionInfo { public final int start; public final int end; protected TagPositionInfo(int start, int end) { this.start = start; this.end = end; } public int length() { return end - start; } } protected int skipAbcName(final int start) { int end = start; byte[] array = buffer.array(); //noinspection StatementWithEmptyBody while (array[++end] != 0) { } return end - start; } }