/*
* $Id: CharstringType2.java,v 1.4 2007-07-26 11:13:44 davidsch Exp $
*
* Typecast - The Font Development Environment
*
* Copyright (c) 2004-2007 David Schweinsberg
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jogamp.graph.font.typecast.ot.table;
import jogamp.graph.font.typecast.ot.table.CffTable;
/**
* CFF Type 2 Charstring
* @version $Id: CharstringType2.java,v 1.4 2007-07-26 11:13:44 davidsch Exp $
* @author <a href="mailto:davidsch@dev.java.net">David Schweinsberg</a>
*/
public class CharstringType2 extends Charstring {
private static final String[] _oneByteOperators = {
"-Reserved-",
"hstem",
"-Reserved-",
"vstem",
"vmoveto",
"rlineto",
"hlineto",
"vlineto",
"rrcurveto",
"-Reserved-",
"callsubr",
"return",
"escape",
"-Reserved-",
"endchar",
"-Reserved-",
"-Reserved-",
"-Reserved-",
"hstemhm",
"hintmask",
"cntrmask",
"rmoveto",
"hmoveto",
"vstemhm",
"rcurveline",
"rlinecurve",
"vvcurveto",
"hhcurveto",
"shortint",
"callgsubr",
"vhcurveto",
"hvcurveto"
};
private static final String[] _twoByteOperators = {
"-Reserved- (dotsection)",
"-Reserved-",
"-Reserved-",
"and",
"or",
"not",
"-Reserved-",
"-Reserved-",
"-Reserved-",
"abs",
"add",
"sub",
"div",
"-Reserved-",
"neg",
"eq",
"-Reserved-",
"-Reserved-",
"drop",
"-Reserved-",
"put",
"get",
"ifelse",
"random",
"mul",
"-Reserved-",
"sqrt",
"dup",
"exch",
"index",
"roll",
"-Reserved-",
"-Reserved-",
"-Reserved-",
"hflex",
"flex",
"hflex1",
"flex1",
"-Reserved-"
};
private final int _index;
private final String _name;
private final int[] _data;
private final int _offset;
private final int _length;
private final CffTable.Index _localSubrIndex;
private final CffTable.Index _globalSubrIndex;
private int _ip;
/** Creates a new instance of CharstringType2 */
protected CharstringType2(
final int index,
final String name,
final int[] data,
final int offset,
final int length,
final CffTable.Index localSubrIndex,
final CffTable.Index globalSubrIndex) {
_index = index;
_name = name;
_data = data;
_offset = offset;
_length = length;
_localSubrIndex = localSubrIndex;
_globalSubrIndex = globalSubrIndex;
}
@Override
public int getIndex() {
return _index;
}
@Override
public String getName() {
return _name;
}
private void disassemble(final StringBuilder sb) {
Number operand = null;
while (isOperandAtIndex()) {
operand = nextOperand();
sb.append(operand).append(" ");
}
int operator = nextByte();
String mnemonic;
if (operator == 12) {
operator = nextByte();
// Check we're not exceeding the upper limit of our mnemonics
if (operator > 38) {
operator = 38;
}
mnemonic = _twoByteOperators[operator];
} else {
mnemonic = _oneByteOperators[operator];
}
sb.append(mnemonic);
}
public void resetIP() {
_ip = _offset;
}
public boolean isOperandAtIndex() {
final int b0 = _data[_ip];
if ((32 <= b0 && b0 <= 255) || b0 == 28) {
return true;
}
return false;
}
public Number nextOperand() {
final int b0 = _data[_ip];
if (32 <= b0 && b0 <= 246) {
// 1 byte integer
++_ip;
return Integer.valueOf(b0 - 139);
} else if (247 <= b0 && b0 <= 250) {
// 2 byte integer
final int b1 = _data[_ip + 1];
_ip += 2;
return Integer.valueOf((b0 - 247) * 256 + b1 + 108);
} else if (251 <= b0 && b0 <= 254) {
// 2 byte integer
final int b1 = _data[_ip + 1];
_ip += 2;
return Integer.valueOf(-(b0 - 251) * 256 - b1 - 108);
} else if (b0 == 28) {
// 3 byte integer
final int b1 = _data[_ip + 1];
final int b2 = _data[_ip + 2];
_ip += 3;
return Integer.valueOf(b1 << 8 | b2);
} else if (b0 == 255) {
// 16-bit signed integer with 16 bits of fraction
final int b1 = (byte) _data[_ip + 1];
final int b2 = _data[_ip + 2];
final int b3 = _data[_ip + 3];
final int b4 = _data[_ip + 4];
_ip += 5;
return Float.valueOf((b1 << 8 | b2) + ((b3 << 8 | b4) / 65536f));
} else {
return null;
}
}
public int nextByte() {
return _data[_ip++];
}
public boolean moreBytes() {
return _ip < _offset + _length;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
resetIP();
while (moreBytes()) {
disassemble(sb);
sb.append("\n");
}
return sb.toString();
}
}