// Copyright 2001, FreeHEP.
package org.freehep.postscript;
import java.lang.reflect.Field;
/**
* OperandStack for PostScript Processor
*
* @author Mark Donszelmann
* @version $Id: DictionaryStack.java 8958 2006-09-12 23:37:43Z duns $
*/
public class DictionaryStack extends PostScriptStack implements NameLookup {
private Class[] operators = {
GeneralOperator.class, StackOperator.class,
ArithmeticOperator.class, ArrayOperator.class,
PackedArrayOperator.class, DictionaryOperator.class, StringOperator.class,
RelationalOperator.class, ControlOperator.class, ConversionOperator.class,
FileOperator.class,
GraphicsStateOperator.class, DeviceOperator.class, MatrixOperator.class,
MemoryOperator.class, MiscellaneousOperator.class,
PathOperator.class, PaintingOperator.class,
FormOperator.class,
OutputOperator.class, FontOperator.class, ExtraOperator.class
};
private static String[] standardEncodingArray = {
".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
"space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright",
"parenleft", "parenright", "asterisk", "plus", "comma", "minus", "period", "slash",
"zero", "one", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question",
"at", "A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N", "O",
"P", "Q", "R", "S", "T", "U", "V", "W",
"X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
"quoteleft", "a", "b", "c", "d", "e", "f", "g",
"h", "i", "j", "k", "l", "m", "n", "o",
"p", "q", "r", "s", "t", "u", "v", "w",
"x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
".notdef", "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section",
"currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl",
".notdef", "endash", "dagger", "daggerdbl", "periodcentered", ".notdef", "paragraph", "bullet",
"quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", ".notdef", "questiondown",
".notdef", "grave", "acute", "circonflex", "tilde", "macron", "breve", "dotaccent",
"dieresis", ".notdef", "ring", "cedilla", ".notdef", "hungarumlaut", "ogonek", "caron",
"emdash", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
".notdef", "AE", ".notdef", "ordfeminine", ".notdef", ".notdef", ".notdef", ".notdef",
"Lslash", "Oslash", "OE", "ordmasculine", ".notdef", ".notdef", ".notdef", ".notdef",
".notdef", "ae", ".notdef", ".notdef", ".notdef", "dotlessi", ".notdef", ".notdef",
"lslash", "oslash", "oe", "germandbls", ".notdef", ".notdef", ".notdef", ".notdef"
};
private static String[] isoLatin1EncodingArray = {
".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
"space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright",
"parenleft", "parenright", "asterisk", "plus", "comma", "minus", "period", "slash",
"zero", "one", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question",
"at", "A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N", "O",
"P", "Q", "R", "S", "T", "U", "V", "W",
"X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
"quoteleft", "a", "b", "c", "d", "e", "f", "g",
"h", "i", "j", "k", "l", "m", "n", "o",
"p", "q", "r", "s", "t", "u", "v", "w",
"x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
"dotlessi", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent",
"dieresis", ".notdef", "ring", "cedilla", ".notdef", "hungarumlaut", "ogonek", "caron",
"space", "exclamdown", "cent", "sterling", "currency", "yen", "brokenbar", "section",
"dieresis", "copyright", "ordfeminine", "guillemotleft", "logicalnot", "hyphen", "registered", "macron",
"degree", "plusminus", "twosuperior", "threesuperior", "acute", "mu", "paragraph", "periodcentered",
"cedilla", "onesuperior", "ordmasculine", "guillemotright", "onequarter", "onehalf", "threequarters", "questiondown",
"Agrave", "Aacute", "Acircumflex", "Atilde", "Adieresis", "Aring", "AE", "Ccedilla",
"Egrave", "Eacute", "Ecircumflex", "Edieresis", "Igrave", "Iacute", "Icircumflex", "Idieresis",
"Dcroat", "Ntilde", "Ograve", "Oacute", "Ocircumflex", "Otilde", "Odieresis", "multiply",
"Oslash", "Ugrave", "Uacute", "Ucircumflex", "Udieresis", "Yacute", "Thorn", "germandbls",
"agrave", "aacute", "acircumflex", "atilde", "adieresis", "aring", "ae", "ccedilla",
"egrave", "eacute", "ecircumflex", "edieresis", "igrave", "iacute", "icircumflex", "idieresis",
"dcroat", "ntilde", "ograve", "oacute", "ocircumflex", "otilde", "odieresis", "divide",
"oslash", "ugrave", "uacute", "ucircumflex", "udieresis", "yacute", "thorn", "ydieresis"
};
private PSName errordict = new PSName("errordict");
private PSName dollarerror = new PSName("$error");
private PSName systemdict = new PSName("systemdict");
private PSName userdict = new PSName("userdict");
private PSName globaldict = new PSName("globaldict");
private PSName statusdict = new PSName("statusdict");
private PSName standardEncoding = new PSName("StandardEncoding");
private PSName isoLatin1Encoding = new PSName("ISOLatin1Encoding");
private PSName fontDirectory = new PSName("FontDirectory");
private PSName globalFontDirectory = new PSName("GlobalFontDirectory");
public DictionaryStack() {
super();
// fill error dictionary
PSDictionary error = new PSDictionary();
error.setName("errordict");
Class[] errorClass = ErrorOperator.operators;
for (int i=0; i<errorClass.length; i++) {
addOperator(error, errorClass[i]);
}
// fill $error dictionary
PSDictionary dollarErrorDict = new PSDictionary();
dollarErrorDict.setName("$error");
dollarErrorDict.put("newerror", new PSBoolean(false));
dollarErrorDict.put("errorname", new PSNull());
dollarErrorDict.put("command", new PSNull());
dollarErrorDict.put("errorinfo", new PSNull());
dollarErrorDict.put("ostack", new PSNull());
dollarErrorDict.put("estack", new PSNull());
dollarErrorDict.put("dstack", new PSNull());
dollarErrorDict.put("recordstacks", new PSBoolean(true));
dollarErrorDict.put("binary", new PSBoolean(false));
PSDictionary user = new PSDictionary();
user.setName("userdict");
PSDictionary global = new PSDictionary();
global.setName("globaldict");
PSDictionary status = new PSDictionary();
status.setName("statusdict");
// fill system dictionary
PSDictionary system = new PSDictionary();
system.setName("systemdict");
system.put(systemdict, system);
system.put(errordict, error);
system.put(dollarerror, dollarErrorDict);
system.put(userdict, user);
system.put(statusdict, status);
system.put(globaldict, global);
for (int i=0; i<operators.length; i++) {
try {
Field f = operators[i].getField("operators");
Class[] opClass = (Class[])f.get(null);
for (int j=0; j<opClass.length; j++) {
addOperator(system, opClass[j]);
}
} catch (NoSuchFieldException e) {
System.err.println("Error: "+operators[i]+" does not have 'operators' field.");
} catch (IllegalAccessException e) {
System.err.println("Error: "+operators[i]+", no access to 'operators' field.");
}
}
// add encodings
system.put(standardEncoding, standardEncodingArray);
system.put(isoLatin1Encoding, isoLatin1EncodingArray);
// add font directories
system.put(fontDirectory, new PSDictionary());
// FIXME: should be a different directory
system.put(globalFontDirectory, system.get(fontDirectory));
// others
system.put(new PSName("null"), new PSNull());
system.put(new PSName("languagelevel"), new PSInteger(2));
// create dictionary stack
push(system);
push(global);
push(user);
}
private void addOperator(PSDictionary dict, Class clazz) {
try {
PSOperator op = (PSOperator)clazz.newInstance();
PSName key = new PSName(op.getName());
if (dict.get(key) == null) {
dict.put(key, op);
op.setName(key.cvs());
} else {
System.out.println("Duplicate operator '"+key+"'");
System.exit(1);
}
} catch (ClassCastException e) {
System.err.println("Error: "+clazz+" does not inherit from PSOperator.\n"+e);
} catch (IllegalAccessException e) {
System.err.println("Error: "+clazz+" cannot be instantiated.\n"+e);
} catch (InstantiationException e) {
System.err.println("Error: "+clazz+" cannot be instantiated.\n"+e);
}
}
public Object push(Object o){
throw new IllegalArgumentException("Only PSDictionary allowed on stack.");
}
public PSDictionary push(PSDictionary d) {
return (PSDictionary)super.push(d);
}
public Object pop() {
if (elementCount <= 3) {
return null;
}
return super.pop();
}
public PSDictionary popDictionary() {
return (PSDictionary)pop();
}
public void clear() {
for (int i = 3; i < elementCount; i++) {
elementData[i] = null;
}
elementCount = 3;
}
public PSDictionary systemDictionary() {
return (PSDictionary)elementData[0];
}
public PSDictionary globalDictionary() {
return (PSDictionary)elementData[1];
}
public PSDictionary userDictionary() {
return (PSDictionary)elementData[2];
}
public PSDictionary errorDictionary() {
return (PSDictionary)systemDictionary().get(errordict);
}
public PSDictionary dollarError() {
return (PSDictionary)systemDictionary().get(dollarerror);
}
public PSDictionary currentDictionary() {
return (PSDictionary)elementData[elementCount-1];
}
public PSDictionary fontDirectory() {
return (PSDictionary)systemDictionary().get(fontDirectory);
}
public PSDictionary globalFontDirectory() {
return (PSDictionary)systemDictionary().get(globalFontDirectory);
}
public PSDictionary get(PSObject key) {
for (int i=elementCount-1; i>=0; i--) {
PSDictionary d = (PSDictionary)elementData[i];
if (d.get(key) != null) {
return d;
}
}
return null;
}
public PSObject lookup(PSObject key) {
PSDictionary d = get(key);
return (d != null) ? d.get(key) : null;
}
public void printStack() {
System.out.println();
System.out.println("== Top Dictionary Stack ==");
super.printStack();
System.out.println("== Bottom Dictionary Stack ==");
}
public String toString() {
return "DictionaryStack";
}
}