// Copyright 2001, FreeHEP.
package org.freehep.graphicsio.font.truetype;
import java.io.IOException;
/**
* CMAP Table.
*
* @author Simon Fischer
* @version $Id: TTFCMapTable.java,v 1.5 2009-08-17 21:44:45 murkle Exp $
*/
public class TTFCMapTable extends TTFTable {
public class EncodingTable {
public int platformID;
public int encodingID;
public long offset;
public int format;
public int length;
public int version;
public TableFormat tableFormat;
public void readHeader() throws IOException {
platformID = ttf.readUShort();
encodingID = ttf.readUShort();
offset = ttf.readULong();
}
public void readBody() throws IOException {
ttf.seek(offset);
format = ttf.readUShort();
length = ttf.readUShort();
version = ttf.readUShort();
switch (format) {
case 0:
tableFormat = new TableFormat0();
break;
case 4:
tableFormat = new TableFormat4();
break;
case 2:
case 6:
System.err.println(
"Unimplementet encoding table format: " + format);
break;
default:
System.err.println(
"Illegal value for encoding table format: " + format);
break;
}
if (tableFormat != null) {
tableFormat.read();
}
}
@Override
public String toString() {
String str = "[encoding] PID:" + platformID + " EID:" + encodingID
+ " format:" + format + " v" + version
+ (tableFormat != null ? tableFormat.toString()
: " [no data read]");
return str;
}
}
public abstract class TableFormat {
public abstract void read() throws IOException;
public abstract int getGlyphIndex(int character);
}
public class TableFormat0 extends TableFormat {
public int[] glyphIdArray = new int[256];
@Override
public void read() throws IOException {
for (int i = 0; i < glyphIdArray.length; i++) {
glyphIdArray[i] = ttf.readByte();
}
}
@Override
public String toString() {
String str = "";
for (int i = 0; i < glyphIdArray.length; i++) {
if (i % 16 == 0) {
str += "\n " + Integer.toHexString(i / 16) + "x: ";
}
String number = glyphIdArray[i] + "";
while (number.length() < 3) {
number = " " + number;
}
str += number + " ";
}
return str;
}
@Override
public int getGlyphIndex(int character) {
return glyphIdArray[character];
}
}
public class TableFormat4 extends TableFormat {
public int segCount;
public int[] endCount, startCount, idRangeOffset;
public short[] idDelta; // could be int (ushort) as well
@Override
public void read() throws IOException {
segCount = ttf.readUShort() / 2;
// dump the next three ushorts to /dev/null as they guy
// who invented them really must have drunk a lot
ttf.readUShort();
ttf.readUShort();
ttf.readUShort();
// endCount = readFFFFTerminatedUShortArray();
endCount = ttf.readUShortArray(segCount);
int reservedPad = ttf.readUShort();
if (reservedPad != 0) {
System.err
.println("reservedPad not 0, but " + reservedPad + ".");
}
startCount = ttf.readUShortArray(endCount.length);
// the deltas should be unsigned, but due to
// modulo arithmetic it makes no difference
idDelta = ttf.readShortArray(endCount.length);
idRangeOffset = ttf.readUShortArray(endCount.length);
}
@Override
public String toString() {
String str = "\n " + endCount.length + " sections:";
for (int i = 0; i < endCount.length; i++) {
str += "\n " + startCount[i] + " to " + endCount[i] + " : "
+ idDelta[i] + " (" + idRangeOffset[i] + ")";
}
return str;
}
@Override
public int getGlyphIndex(int character) {
return 0;
}
}
public int version;
public EncodingTable encodingTable[];
@Override
public String getTag() {
return "cmap";
}
@Override
public void readTable() throws IOException {
version = ttf.readUShort();
encodingTable = new EncodingTable[ttf.readUShort()];
for (int i = 0; i < encodingTable.length; i++) {
encodingTable[i] = new EncodingTable();
encodingTable[i].readHeader();
}
for (int i = 0; i < encodingTable.length; i++) {
encodingTable[i].readBody();
}
}
@Override
public String toString() {
String str = super.toString() + " v" + version;
for (int i = 0; i < encodingTable.length; i++) {
str += "\n " + encodingTable[i];
}
return str;
}
}