package com.sun.javafx.font;
import java.util.Arrays;
import java.util.Comparator;
import java.util.zip.Inflater;
import com.sun.javafx.font.FontFileReader.Buffer;
class WoffDecoder extends FontFileWriter {
WoffHeader ;
WoffDirectoryEntry[] woffTableDirectory;
public WoffDecoder() {
super();
}
public void decode(FontFileReader input) throws Exception {
input.reset();
initWoffTables(input);
if (woffHeader == null || woffTableDirectory == null) {
throw new Exception("WoffDecoder: failure reading header");
}
int format = woffHeader.flavor;
if (format != v1ttTag && format != trueTag && format != ottoTag) {
throw new Exception("WoffDecoder: invalid flavor");
}
short numTables = woffHeader.numTables;
setLength(woffHeader.totalSfntSize);
writeHeader(format, numTables);
Arrays.sort(woffTableDirectory, (o1, o2) -> o1.offset - o2.offset);
Inflater decompressor = new Inflater();
int offset = TTCHEADERSIZE + numTables * DIRECTORYENTRYSIZE;
for (int i = 0; i < woffTableDirectory.length; i++) {
WoffDirectoryEntry table = woffTableDirectory[i];
writeDirectoryEntry(table.index, table.tag, table.origChecksum,
offset, table.origLength);
Buffer buffer = input.readBlock(table.offset, table.comLength);
byte[] bytes = new byte[table.comLength];
buffer.get(0, bytes, 0, table.comLength);
if (table.comLength != table.origLength) {
decompressor.setInput(bytes);
byte[] output = new byte[table.origLength];
int length = decompressor.inflate(output);
if (length != table.origLength) {
throw new Exception("WoffDecoder: failure expanding table");
}
decompressor.reset();
bytes = output;
}
seek(offset);
writeBytes(bytes);
offset += (table.origLength + 3) & ~3;
}
decompressor.end();
}
void initWoffTables(FontFileReader input) throws Exception {
long filesize = input.getLength();
if (filesize < WOFFHEADERSIZE) {
throw new Exception("WoffDecoder: invalid filesize");
}
Buffer buffer = input.readBlock(0, WOFFHEADERSIZE);
WoffHeader header = new WoffHeader(buffer);
short numTables = header.numTables;
if (header.signature != woffTag) {
throw new Exception("WoffDecoder: invalid signature");
}
if (header.reserved != 0) {
throw new Exception("WoffDecoder: invalid reserved != 0");
}
if (filesize < WOFFHEADERSIZE + numTables * WOFFDIRECTORYENTRYSIZE) {
throw new Exception ("WoffDecoder: invalid filesize");
}
WoffDirectoryEntry table;
WoffDirectoryEntry[] tableDirectory = new WoffDirectoryEntry[numTables];
int headerOffset = WOFFHEADERSIZE + numTables * WOFFDIRECTORYENTRYSIZE;
int size = TTCHEADERSIZE + numTables * DIRECTORYENTRYSIZE;
buffer = input.readBlock(WOFFHEADERSIZE, numTables * WOFFDIRECTORYENTRYSIZE);
int prevTag = 0;
for (int i=0; i<numTables; i++) {
tableDirectory[i] = table = new WoffDirectoryEntry(buffer, i);
if (table.tag <= prevTag) {
throw new Exception("WoffDecoder: table directory " +
"not ordered by tag");
}
int startOffset = table.offset;
int endOffset = table.offset + table.comLength;
if (!(headerOffset <= startOffset && startOffset <= filesize)) {
throw new Exception("WoffDecoder: invalid table offset");
}
if (!(startOffset <= endOffset && endOffset <= filesize)) {
throw new Exception("WoffDecoder: invalid table offset");
}
if (table.comLength > table.origLength) {
throw new Exception("WoffDecoder: invalid compressed length");
}
size += (table.origLength + 3) & ~3;
if (size > header.totalSfntSize) {
throw new Exception("WoffDecoder: invalid totalSfntSize");
}
}
if (size != header.totalSfntSize) {
throw new Exception("WoffDecoder: invalid totalSfntSize");
}
this.woffHeader = header;
this.woffTableDirectory = tableDirectory;
}
static class {
int ;
int ;
int ;
short ;
short ;
int ;
short ;
short ;
int ;
int ;
int ;
int ;
int ;
(Buffer buffer) {
signature = buffer.getInt();
flavor = buffer.getInt();
length = buffer.getInt();
numTables = buffer.getShort();
reserved = buffer.getShort();
totalSfntSize = buffer.getInt();
majorVersion = buffer.getShort();
minorVersion = buffer.getShort();
metaOffset = buffer.getInt();
metaLength = buffer.getInt();
metaOrigLength = buffer.getInt();
privateOffset = buffer.getInt();
privateLength = buffer.getInt();
}
}
static class WoffDirectoryEntry {
int tag;
int offset;
int comLength;
int origLength;
int origChecksum;
int index;
WoffDirectoryEntry(Buffer buffer, int index) {
tag = buffer.getInt();
offset = buffer.getInt();
comLength = buffer.getInt();
origLength = buffer.getInt();
origChecksum = buffer.getInt();
this.index = index;
}
}
}