Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jpedal.function.PostScriptCompiler Maven / Gradle / Ivy
/*
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info: http://www.idrsolutions.com
* Help section for developers at http://www.idrsolutions.com/support/
*
* (C) Copyright 1997-2016 IDRsolutions and Contributors.
*
* This file is part of JPedal/JPDF2HTML5
*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ---------------
* PostScriptCompiler.java
* ---------------
*/
package org.jpedal.function;
import java.util.Arrays;
import java.util.Stack;
//class will be used in future for speed execution
public class PostScriptCompiler {
private static final int C_ABS = 96370;
private static final int C_ADD = 96417;
private static final int C_ATAN = 3004320;
private static final int C_CEILING = 660387005;
private static final int C_COS = 98695;
private static final int C_CVI = 98902;
private static final int C_CVR = 98911;
private static final int C_DIV = 99473;
private static final int C_EXP = 100893;
private static final int C_FLOOR = 97526796;
private static final int C_IDIV = 3227528;
private static final int C_LN = 3458;
private static final int C_LOG = 107332;
private static final int C_MOD = 108290;
private static final int C_MUL = 108484;
private static final int C_NEG = 108944;
private static final int C_SIN = 113880;
private static final int C_SQRT = 3538208;
private static final int C_SUB = 114240;
private static final int C_ROUND = 108704142;
private static final int C_TRUNCATE = 1852984678;
private static final int C_AND = 96727;
private static final int C_BITSHIFT = 1125715861;
private static final int C_EQ = 3244;
private static final int C_FALSE = 97196323;
private static final int C_GE = 3294;
private static final int C_GT = 3309;
private static final int C_LE = 3449;
private static final int C_LT = 3464;
private static final int C_NE = 3511;
private static final int C_NOT = 109267;
private static final int C_OR = 3555;
private static final int C_TRUE = 3569038;
private static final int C_XOR = 118875;
private static final int C_IF = 3357;
private static final int C_IFELSE = -1191590954;
private static final int C_COPY = 3059573;
private static final int C_EXCH = 3127384;
private static final int C_POP = 111185;
private static final int C_DUP = 99839;
private static final int C_INDEX = 100346066;
private static final int C_ROLL = 3506301;
private static final int T_COMMAND = 1;
private static final int T_NUMBER = 2;
private static final int T_BOOLEAN = 3;
private static final int T_SBRACE = 123; //start brace
private static final int T_EBRACE = 125; //end brace
private static final double radToDegrees = 180f / Math.PI;
private static final double toBase10=Math.log(10);
private static final byte[] CHAR256 = {
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F,
1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 2, 0, 2, 0, // 3
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
};
private final double[] dValues = new double[200]; //hold default values
private final int[] dTypes = new int[200]; //hold default types
private final double[] cValues = new double[250];
private final int[] cTypes = new int[250];
private int sp = 0;//stream pointer
private int dp = 0;//default pointer
private int cp = 0;//cur list pointer
private final Stack braces = new Stack();
public PostScriptCompiler(final byte[] stream) {
parseStream(stream);
}
private void parseStream(byte[] stream) {
int len = stream.length;
while (sp < len) {
int cc = stream[sp++] & 0xff;
if (cc == T_SBRACE) {
if (!braces.empty()) {
pushDefault(T_SBRACE, T_SBRACE);
}
braces.push(Boolean.TRUE);
} else if (cc == T_EBRACE) {
braces.pop();
if (!braces.empty()) {
pushDefault(T_EBRACE, T_EBRACE);
}
} else if (isDigit(cc) || isFullStop(cc) || cc == 43 || cc == 45) {
StringBuilder sb = new StringBuilder();
while (sp < len) {
if (isWhiteSpace(cc) || isDelimiter(cc)) {
sp--;
break;
} else {
sb.append((char) cc);
cc = stream[sp++] & 0xff;
}
}
pushDefault(Double.parseDouble(sb.toString()), T_NUMBER);
} else if (cc > 96 && cc < 123) {
StringBuilder sb = new StringBuilder();
while (sp < len) {
if (isWhiteSpace(cc) || isDelimiter(cc)) {
sp--;
break;
} else {
sb.append((char) cc);
cc = stream[sp++] & 0xff;
}
}
int com = getCommand(sb.toString());
if (com != -1) {
pushDefault(com, T_COMMAND);
}
}
}
System.out.println(new String(stream));
}
private static int getCommand(String s) {
switch (s.hashCode()) {
case C_ABS:
return C_ABS;
case C_ADD:
return C_ADD;
case C_ATAN:
return C_ATAN;
case C_CEILING:
return C_CEILING;
case C_COS:
return C_COS;
case C_CVI:
return C_CVI;
case C_CVR:
return C_CVR;
case C_DIV:
return C_DIV;
case C_EXP:
return C_EXP;
case C_FLOOR:
return C_FLOOR;
case C_IDIV:
return C_IDIV;
case C_LN:
return C_LN;
case C_LOG:
return C_LOG;
case C_MOD:
return C_MOD;
case C_MUL:
return C_MUL;
case C_NEG:
return C_NEG;
case C_SIN:
return C_SIN;
case C_SQRT:
return C_SQRT;
case C_SUB:
return C_SUB;
case C_ROUND:
return C_ROUND;
case C_TRUNCATE:
return C_TRUNCATE;
case C_AND:
return C_AND;
case C_BITSHIFT:
return C_BITSHIFT;
case C_EQ:
return C_EQ;
case C_FALSE:
return C_FALSE;
case C_GE:
return C_GE;
case C_GT:
return C_GT;
case C_LE:
return C_LE;
case C_LT:
return C_LT;
case C_NE:
return C_NE;
case C_NOT:
return C_NOT;
case C_OR:
return C_OR;
case C_TRUE:
return C_TRUE;
case C_XOR:
return C_XOR;
case C_IF:
return C_IF;
case C_IFELSE:
return C_IFELSE;
case C_COPY:
return C_COPY;
case C_EXCH:
return C_EXCH;
case C_POP:
return C_POP;
case C_DUP:
return C_DUP;
case C_INDEX:
return C_INDEX;
case C_ROLL:
return C_ROLL;
}
return -1;
}
private void pushDefault(double value, int type) {
dValues[dp] = value;
dTypes[dp] = type;
dp++;
}
private static boolean isWhiteSpace(int ch) {
return CHAR256[ch] == 1;
}
private static boolean isDigit(int ch) {
return CHAR256[ch] == 4;
}
private static boolean isFullStop(int ch) {
return ch == 46;
}
public static boolean isDelimiter(int ch) {
return CHAR256[ch] == 2;
}
private void executeCommand(int cmd) {
double[] first;
double[] second;
int n,j;
switch (cmd) {
case C_ABS:
first = popItem();
cValues[cp] = Math.abs(first[0]);
cTypes[cp] = (int) first[1];
cp++;
break;
case C_ADD:
first = popItem();
second = popItem();
cValues[cp] = first[0] + second[0];
cTypes[cp] = (int) first[1];
cp++;
break;
case C_ATAN:
first = popItem();
second = popItem();
double tt = 0;
final double tangent = second[0]/first[0];
if(first[0]>=0 && second[0]>=0){
tt = Math.toDegrees(Math.atan(tangent));
} else if (first[0]>0 && second[0]<=0){
double tmp = Math.abs(Math.toDegrees(Math.atan(tangent)));
tt = tmp+90;
} else if (first[0]<=0 && second[0]<=0){
double tmp = Math.abs(Math.toDegrees(Math.atan(tangent)));
tt = tmp+180;
} else if (first[0]<=0 && second[0]>=0){
double tmp = Math.abs(Math.toDegrees(Math.atan(tangent)));
tt = tmp + 270;
}
cValues[cp] = tt;
cTypes[cp] = (int) first[1];
cp++;
break;
case C_CEILING:
first = popItem();
cValues[cp] = Math.ceil(first[0]);
cTypes[cp] = (int) first[1];
cp++;
break;
case C_COS:
first = popItem();
cValues[cp] = Math.sin(first[0] / radToDegrees);
cTypes[cp] = (int) first[1];
cp++;
break;
case C_CVI:
first = popItem();
cValues[cp] = (int) first[0];
cTypes[cp] = (int) first[1];
cp++;
break;
case C_CVR:
first = popItem();
cValues[cp] = first[0];
cTypes[cp] = (int) first[1];
cp++;
break;
case C_DIV:
first = popItem();
second = popItem();
cValues[cp] = second[0] / first[0];
cTypes[cp] = (int) first[1];
cp++;
break;
case C_EXP:
first = popItem();
second = popItem();
cValues[cp] = Math.pow(second[0],first[0]);
cTypes[cp] = (int) first[1];
break;
case C_FLOOR:
first = popItem();
cValues[cp] = Math.floor(first[0]);
cTypes[cp] = (int) first[1];
cp++;
break;
case C_IDIV:
first = popItem();
second = popItem();
cValues[cp] = ((int) second[0]) / ((int) first[0]);
cTypes[cp] = (int) first[1];
cp++;
break;
case C_LN:
first = popItem();
cValues[cp] = Math.log(first[0]);
cTypes[cp] = (int) first[1];
cp++;
break;
case C_LOG:
first = popItem();
cValues[cp] = Math.log(first[0])/toBase10;
cTypes[cp] = (int) first[1];
cp++;
break;
case C_MOD:
first = popItem();
second = popItem();
cValues[cp] = ((int) second[0]) % ((int) first[0]);
cTypes[cp] = (int) first[1];
cp++;
break;
case C_MUL:
first = popItem();
second = popItem();
cValues[cp] = first[0] * second[0];
cTypes[cp] = (int) first[1];
cp++;
break;
case C_NEG:
first = popItem();
cValues[cp] = -first[0];
cTypes[cp] = (int) first[1];
cp++;
break;
case C_SIN:
first = popItem();
cValues[cp] = Math.sin(first[0] / radToDegrees);
cTypes[cp] = (int) first[1];
cp++;
break;
case C_SQRT:
first = popItem();
cValues[cp] = Math.sqrt(first[0]);
cTypes[cp] = (int) first[1];
cp++;
break;
case C_SUB:
first = popItem();
second = popItem();
cValues[cp] = second[0] - first[0];
cTypes[cp] = (int) first[1];
cp++;
break;
case C_ROUND:
first = popItem();
cValues[cp] = Math.round(first[0]);
cTypes[cp] = (int) first[1];
cp++;
break;
case C_TRUNCATE:
first = popItem();
cValues[cp] = (int)(first[0]);
cTypes[cp] = (int) first[1];
cp++;
break;
case C_AND:
first = popItem();
second = popItem();
if(first[1] == T_NUMBER && second[1] == T_NUMBER){
cValues[cp] = ((int)second[0]) & ((int)first[0]);
cTypes[cp] = T_NUMBER;
}else{
cValues[cp] = first[0] == second[0] ? 1 : 0 ;
cTypes[cp] = T_BOOLEAN;
}
cp++;
break;
case C_BITSHIFT:
first = popItem();
second = popItem();
cValues[cp] = ((int)second[0])<<((int)first[0]);
cTypes[cp] = (int)first[1];
cp++;
break;
case C_EQ:
first = popItem();
second = popItem();
cValues[cp] = first[0] == second[0] ? 1 : 0;
cTypes[cp] = T_BOOLEAN;
cp++;
break;
case C_FALSE:
cValues[cp] = 0;
cTypes[cp] = T_BOOLEAN;
cp++;
break;
case C_GE:
first = popItem();
second = popItem();
cValues[cp] = second[0] >= first[0] ? 1 : 0;
cTypes[cp] = T_BOOLEAN;
cp++;
break;
case C_GT:
first = popItem();
second = popItem();
cValues[cp] = second[0] > first[0] ? 1 : 0;
cTypes[cp] = T_BOOLEAN;
cp++;
break;
case C_LE:
first = popItem();
second = popItem();
cValues[cp] = second[0] <= first[0] ? 1 : 0;
cTypes[cp] = T_BOOLEAN;
cp++;
break;
case C_LT:
first = popItem();
second = popItem();
cValues[cp] = second[0] < first[0] ? 1 : 0;
cTypes[cp] = T_BOOLEAN;
cp++;
break;
case C_NE:
first = popItem();
second = popItem();
cValues[cp] = second[0] != first[0] ? 1 : 0;
cTypes[cp] = T_BOOLEAN;
cp++;
break;
case C_NOT:
first = popItem();
if(first[1] == T_NUMBER){
}else{
cValues[cp] = first[0] != 1 ? 1 : 0;
}
cTypes[cp] = (int)first[1];
cp++;
break;
case C_OR:
first = popItem();
second = popItem();
if(first[1] == T_NUMBER && second[1] == T_NUMBER){
cValues[cp] = ((int)second[0]) | ((int)first[0]);
cTypes[cp] = T_NUMBER;
}else{
cValues[cp] = first[0]==1 || second[0]==1 ? 1 : 0 ;
cTypes[cp] = T_BOOLEAN;
}
cp++;
break;
case C_TRUE:
cValues[cp] = 1;
cTypes[cp] = T_BOOLEAN;
cp++;
break;
case C_XOR:
first = popItem();
second = popItem();
cValues[cp] = ((int)second[0]) ^ ((int)first[0]);
if(first[1] == T_NUMBER && second[1] == T_NUMBER){
cTypes[cp] = T_NUMBER;
}else{
cTypes[cp] = T_BOOLEAN;
}
cp++;
break;
case C_IF:
//todo
popItem();
break;
case C_IFELSE:
//todo
popItem();
break;
case C_COPY:
first = popItem();
if(first[0]>1){
n = (int)first[0];
double [] values = new double[n];
int [] types = new int[n];
System.arraycopy(cValues, cValues.length-n , values, 0, n);
System.arraycopy(cTypes, cValues.length-n , types, 0, n);
for (int i = 0; i < n; i++) {
cValues[cp] = values[0];
cTypes[cp] = types[1];
cp++;
}
}
break;
case C_EXCH:
first = popItem();
second = popItem();
cValues[cp] = first[0];
cTypes[cp] = (int)first[1];
cp++;
cValues[cp] = second[0];
cTypes[cp] = (int)second[1];
cp++;
break;
case C_POP:
popItem();
break;
case C_DUP:
cValues[cp] = cValues[cp - 1];
cTypes[cp] = cTypes[cp - 1];
cp++;
break;
case C_INDEX:
first = popItem();
n = (int)first[0];
cValues[cp] = cValues[cp - 1 - n];
cTypes[cp] = cTypes[cp - 1 - n];
cp++;
break;
case C_ROLL:
j = (int)popItem()[0];
n = (int)popItem()[0];
double [] values = new double[n];
int [] types = new int[n];
System.arraycopy(cValues, cValues.length-n , values, 0, n);
System.arraycopy(cTypes, cValues.length-n , types, 0, n);
for (int x = 0; x < j; x++) {
for (int i = 0; i < n; i++) {
cValues[cp] = values[0];
cTypes[cp] = types[1];
cp++;
}
}
break;
}
}
private double[] popItem() {
cp--;
return new double[]{cValues[cp], cTypes[cp]};
}
public double[] executeScript(float[] inp) {
Arrays.fill(cValues, 0);
cp = inp.length;
int dLen = dValues.length;
dp = 0;
System.arraycopy(inp, 0, cValues, 0, inp.length);
int type;
double value;
while (dp < dLen) {
type = dTypes[dp];
value = dValues[dp];
switch (type) {
case T_COMMAND:
executeCommand((int) value);
dp++;
break;
case T_NUMBER:
cValues[cp] = dValues[dp];
cTypes[cp] = dTypes[dp];
cp++;
dp++;
break;
case T_SBRACE:
while(dTypes[dp] == T_EBRACE){
dp++;
}
break;
default:
dp++;
}
}
return cValues;
}
// public static void main(String[] args) {
// String[] cmds = new String[]{
// "abs", "add", "atan", "ceiling", "cos", "cvi", "cvr", "div", "exp", "floor", "idiv",
// "ln", "log", "mod", "mul", "neg", "sin", "sqrt", "sub", "round", "truncate", "and",
// "bitshift", "eq", "false", "ge", "gt", "le", "lt", "ne", "not", "or", "true", "xor",
// "if", "ifelse", "copy", "exch", "pop", "dup", "index", "roll"};
//
// for (String cmd : cmds) {
//// System.out.println("case C_" + cmd.toUpperCase() + " :\n return C_" + cmd.toUpperCase() + ";");
// }
//
// String ss = "{ abs }";
// PostScriptCompiler pp = new PostScriptCompiler(ss.getBytes());
//
// float inp[] = new float[]{-5.2f};
//// inp = pp.executeScript(inp);
//
// System.out.println(inp[0]);
// }
}