Convert code in src/core/function.js to use "normal" classes

All of this code predates the existence of native JS classes, however we can now clean this up a bit. This patch thus let us remove some variable "shadowing" from the code.
This commit is contained in:
Jonas Jenwald 2021-02-26 13:15:07 +01:00
parent 061637d3f4
commit e69e8622a9

View File

@ -635,26 +635,28 @@ var PostScriptStack = (function PostScriptStackClosure() {
var MAX_STACK_SIZE = 100; var MAX_STACK_SIZE = 100;
// eslint-disable-next-line no-shadow // eslint-disable-next-line no-shadow
function PostScriptStack(initialStack) { class PostScriptStack {
this.stack = !initialStack constructor(initialStack) {
? [] this.stack = !initialStack
: Array.prototype.slice.call(initialStack, 0); ? []
} : Array.prototype.slice.call(initialStack, 0);
}
PostScriptStack.prototype = { push(value) {
push: function PostScriptStack_push(value) {
if (this.stack.length >= MAX_STACK_SIZE) { if (this.stack.length >= MAX_STACK_SIZE) {
throw new Error("PostScript function stack overflow."); throw new Error("PostScript function stack overflow.");
} }
this.stack.push(value); this.stack.push(value);
}, }
pop: function PostScriptStack_pop() {
pop() {
if (this.stack.length <= 0) { if (this.stack.length <= 0) {
throw new Error("PostScript function stack underflow."); throw new Error("PostScript function stack underflow.");
} }
return this.stack.pop(); return this.stack.pop();
}, }
copy: function PostScriptStack_copy(n) {
copy(n) {
if (this.stack.length + n >= MAX_STACK_SIZE) { if (this.stack.length + n >= MAX_STACK_SIZE) {
throw new Error("PostScript function stack overflow."); throw new Error("PostScript function stack overflow.");
} }
@ -662,12 +664,14 @@ var PostScriptStack = (function PostScriptStackClosure() {
for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++) { for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++) {
stack.push(stack[i]); stack.push(stack[i]);
} }
}, }
index: function PostScriptStack_index(n) {
index(n) {
this.push(this.stack[this.stack.length - n - 1]); this.push(this.stack[this.stack.length - n - 1]);
}, }
// rotate the last n stack elements p times // rotate the last n stack elements p times
roll: function PostScriptStack_roll(n, p) { roll(n, p) {
var stack = this.stack; var stack = this.stack;
var l = stack.length - n; var l = stack.length - n;
var r = stack.length - 1, var r = stack.length - 1,
@ -690,246 +694,245 @@ var PostScriptStack = (function PostScriptStackClosure() {
stack[i] = stack[j]; stack[i] = stack[j];
stack[j] = t; stack[j] = t;
} }
}, }
}; }
return PostScriptStack; return PostScriptStack;
})(); })();
var PostScriptEvaluator = (function PostScriptEvaluatorClosure() {
// eslint-disable-next-line no-shadow class PostScriptEvaluator {
function PostScriptEvaluator(operators) { constructor(operators) {
this.operators = operators; this.operators = operators;
} }
PostScriptEvaluator.prototype = {
execute: function PostScriptEvaluator_execute(initialStack) {
var stack = new PostScriptStack(initialStack);
var counter = 0;
var operators = this.operators;
var length = operators.length;
var operator, a, b;
while (counter < length) {
operator = operators[counter++];
if (typeof operator === "number") {
// Operator is really an operand and should be pushed to the stack.
stack.push(operator);
continue;
}
switch (operator) {
// non standard ps operators
case "jz": // jump if false
b = stack.pop();
a = stack.pop();
if (!a) {
counter = b;
}
break;
case "j": // jump
a = stack.pop();
counter = a;
break;
// all ps operators in alphabetical order (excluding if/ifelse) execute(initialStack) {
case "abs": var stack = new PostScriptStack(initialStack);
a = stack.pop(); var counter = 0;
stack.push(Math.abs(a)); var operators = this.operators;
break; var length = operators.length;
case "add": var operator, a, b;
b = stack.pop(); while (counter < length) {
a = stack.pop(); operator = operators[counter++];
stack.push(a + b); if (typeof operator === "number") {
break; // Operator is really an operand and should be pushed to the stack.
case "and": stack.push(operator);
b = stack.pop(); continue;
a = stack.pop();
if (isBool(a) && isBool(b)) {
stack.push(a && b);
} else {
stack.push(a & b);
}
break;
case "atan":
a = stack.pop();
stack.push(Math.atan(a));
break;
case "bitshift":
b = stack.pop();
a = stack.pop();
if (a > 0) {
stack.push(a << b);
} else {
stack.push(a >> b);
}
break;
case "ceiling":
a = stack.pop();
stack.push(Math.ceil(a));
break;
case "copy":
a = stack.pop();
stack.copy(a);
break;
case "cos":
a = stack.pop();
stack.push(Math.cos(a));
break;
case "cvi":
a = stack.pop() | 0;
stack.push(a);
break;
case "cvr":
// noop
break;
case "div":
b = stack.pop();
a = stack.pop();
stack.push(a / b);
break;
case "dup":
stack.copy(1);
break;
case "eq":
b = stack.pop();
a = stack.pop();
stack.push(a === b);
break;
case "exch":
stack.roll(2, 1);
break;
case "exp":
b = stack.pop();
a = stack.pop();
stack.push(a ** b);
break;
case "false":
stack.push(false);
break;
case "floor":
a = stack.pop();
stack.push(Math.floor(a));
break;
case "ge":
b = stack.pop();
a = stack.pop();
stack.push(a >= b);
break;
case "gt":
b = stack.pop();
a = stack.pop();
stack.push(a > b);
break;
case "idiv":
b = stack.pop();
a = stack.pop();
stack.push((a / b) | 0);
break;
case "index":
a = stack.pop();
stack.index(a);
break;
case "le":
b = stack.pop();
a = stack.pop();
stack.push(a <= b);
break;
case "ln":
a = stack.pop();
stack.push(Math.log(a));
break;
case "log":
a = stack.pop();
stack.push(Math.log(a) / Math.LN10);
break;
case "lt":
b = stack.pop();
a = stack.pop();
stack.push(a < b);
break;
case "mod":
b = stack.pop();
a = stack.pop();
stack.push(a % b);
break;
case "mul":
b = stack.pop();
a = stack.pop();
stack.push(a * b);
break;
case "ne":
b = stack.pop();
a = stack.pop();
stack.push(a !== b);
break;
case "neg":
a = stack.pop();
stack.push(-a);
break;
case "not":
a = stack.pop();
if (isBool(a)) {
stack.push(!a);
} else {
stack.push(~a);
}
break;
case "or":
b = stack.pop();
a = stack.pop();
if (isBool(a) && isBool(b)) {
stack.push(a || b);
} else {
stack.push(a | b);
}
break;
case "pop":
stack.pop();
break;
case "roll":
b = stack.pop();
a = stack.pop();
stack.roll(a, b);
break;
case "round":
a = stack.pop();
stack.push(Math.round(a));
break;
case "sin":
a = stack.pop();
stack.push(Math.sin(a));
break;
case "sqrt":
a = stack.pop();
stack.push(Math.sqrt(a));
break;
case "sub":
b = stack.pop();
a = stack.pop();
stack.push(a - b);
break;
case "true":
stack.push(true);
break;
case "truncate":
a = stack.pop();
a = a < 0 ? Math.ceil(a) : Math.floor(a);
stack.push(a);
break;
case "xor":
b = stack.pop();
a = stack.pop();
if (isBool(a) && isBool(b)) {
stack.push(a !== b);
} else {
stack.push(a ^ b);
}
break;
default:
throw new FormatError(`Unknown operator ${operator}`);
}
} }
return stack.stack; switch (operator) {
}, // non standard ps operators
}; case "jz": // jump if false
return PostScriptEvaluator; b = stack.pop();
})(); a = stack.pop();
if (!a) {
counter = b;
}
break;
case "j": // jump
a = stack.pop();
counter = a;
break;
// all ps operators in alphabetical order (excluding if/ifelse)
case "abs":
a = stack.pop();
stack.push(Math.abs(a));
break;
case "add":
b = stack.pop();
a = stack.pop();
stack.push(a + b);
break;
case "and":
b = stack.pop();
a = stack.pop();
if (isBool(a) && isBool(b)) {
stack.push(a && b);
} else {
stack.push(a & b);
}
break;
case "atan":
a = stack.pop();
stack.push(Math.atan(a));
break;
case "bitshift":
b = stack.pop();
a = stack.pop();
if (a > 0) {
stack.push(a << b);
} else {
stack.push(a >> b);
}
break;
case "ceiling":
a = stack.pop();
stack.push(Math.ceil(a));
break;
case "copy":
a = stack.pop();
stack.copy(a);
break;
case "cos":
a = stack.pop();
stack.push(Math.cos(a));
break;
case "cvi":
a = stack.pop() | 0;
stack.push(a);
break;
case "cvr":
// noop
break;
case "div":
b = stack.pop();
a = stack.pop();
stack.push(a / b);
break;
case "dup":
stack.copy(1);
break;
case "eq":
b = stack.pop();
a = stack.pop();
stack.push(a === b);
break;
case "exch":
stack.roll(2, 1);
break;
case "exp":
b = stack.pop();
a = stack.pop();
stack.push(a ** b);
break;
case "false":
stack.push(false);
break;
case "floor":
a = stack.pop();
stack.push(Math.floor(a));
break;
case "ge":
b = stack.pop();
a = stack.pop();
stack.push(a >= b);
break;
case "gt":
b = stack.pop();
a = stack.pop();
stack.push(a > b);
break;
case "idiv":
b = stack.pop();
a = stack.pop();
stack.push((a / b) | 0);
break;
case "index":
a = stack.pop();
stack.index(a);
break;
case "le":
b = stack.pop();
a = stack.pop();
stack.push(a <= b);
break;
case "ln":
a = stack.pop();
stack.push(Math.log(a));
break;
case "log":
a = stack.pop();
stack.push(Math.log(a) / Math.LN10);
break;
case "lt":
b = stack.pop();
a = stack.pop();
stack.push(a < b);
break;
case "mod":
b = stack.pop();
a = stack.pop();
stack.push(a % b);
break;
case "mul":
b = stack.pop();
a = stack.pop();
stack.push(a * b);
break;
case "ne":
b = stack.pop();
a = stack.pop();
stack.push(a !== b);
break;
case "neg":
a = stack.pop();
stack.push(-a);
break;
case "not":
a = stack.pop();
if (isBool(a)) {
stack.push(!a);
} else {
stack.push(~a);
}
break;
case "or":
b = stack.pop();
a = stack.pop();
if (isBool(a) && isBool(b)) {
stack.push(a || b);
} else {
stack.push(a | b);
}
break;
case "pop":
stack.pop();
break;
case "roll":
b = stack.pop();
a = stack.pop();
stack.roll(a, b);
break;
case "round":
a = stack.pop();
stack.push(Math.round(a));
break;
case "sin":
a = stack.pop();
stack.push(Math.sin(a));
break;
case "sqrt":
a = stack.pop();
stack.push(Math.sqrt(a));
break;
case "sub":
b = stack.pop();
a = stack.pop();
stack.push(a - b);
break;
case "true":
stack.push(true);
break;
case "truncate":
a = stack.pop();
a = a < 0 ? Math.ceil(a) : Math.floor(a);
stack.push(a);
break;
case "xor":
b = stack.pop();
a = stack.pop();
if (isBool(a) && isBool(b)) {
stack.push(a !== b);
} else {
stack.push(a ^ b);
}
break;
default:
throw new FormatError(`Unknown operator ${operator}`);
}
}
return stack.stack;
}
}
// Most of the PDFs functions consist of simple operations such as: // Most of the PDFs functions consist of simple operations such as:
// roll, exch, sub, cvr, pop, index, dup, mul, if, gt, add. // roll, exch, sub, cvr, pop, index, dup, mul, if, gt, add.
@ -938,84 +941,100 @@ var PostScriptEvaluator = (function PostScriptEvaluatorClosure() {
// optimize some expressions using basic math properties. Keeping track of // optimize some expressions using basic math properties. Keeping track of
// min/max values will allow us to avoid extra Math.min/Math.max calls. // min/max values will allow us to avoid extra Math.min/Math.max calls.
var PostScriptCompiler = (function PostScriptCompilerClosure() { var PostScriptCompiler = (function PostScriptCompilerClosure() {
function AstNode(type) { class AstNode {
this.type = type; constructor(type) {
} this.type = type;
AstNode.prototype.visit = function (visitor) { }
unreachable("abstract method");
};
function AstArgument(index, min, max) { visit(visitor) {
AstNode.call(this, "args"); unreachable("abstract method");
this.index = index; }
this.min = min;
this.max = max;
} }
AstArgument.prototype = Object.create(AstNode.prototype);
AstArgument.prototype.visit = function (visitor) {
visitor.visitArgument(this);
};
function AstLiteral(number) { class AstArgument extends AstNode {
AstNode.call(this, "literal"); constructor(index, min, max) {
this.number = number; super("args");
this.min = number; this.index = index;
this.max = number; this.min = min;
} this.max = max;
AstLiteral.prototype = Object.create(AstNode.prototype); }
AstLiteral.prototype.visit = function (visitor) {
visitor.visitLiteral(this);
};
function AstBinaryOperation(op, arg1, arg2, min, max) { visit(visitor) {
AstNode.call(this, "binary"); visitor.visitArgument(this);
this.op = op; }
this.arg1 = arg1;
this.arg2 = arg2;
this.min = min;
this.max = max;
} }
AstBinaryOperation.prototype = Object.create(AstNode.prototype);
AstBinaryOperation.prototype.visit = function (visitor) {
visitor.visitBinaryOperation(this);
};
function AstMin(arg, max) { class AstLiteral extends AstNode {
AstNode.call(this, "max"); constructor(number) {
this.arg = arg; super("literal");
this.min = arg.min; this.number = number;
this.max = max; this.min = number;
} this.max = number;
AstMin.prototype = Object.create(AstNode.prototype); }
AstMin.prototype.visit = function (visitor) {
visitor.visitMin(this);
};
function AstVariable(index, min, max) { visit(visitor) {
AstNode.call(this, "var"); visitor.visitLiteral(this);
this.index = index; }
this.min = min;
this.max = max;
} }
AstVariable.prototype = Object.create(AstNode.prototype);
AstVariable.prototype.visit = function (visitor) {
visitor.visitVariable(this);
};
function AstVariableDefinition(variable, arg) { class AstBinaryOperation extends AstNode {
AstNode.call(this, "definition"); constructor(op, arg1, arg2, min, max) {
this.variable = variable; super("binary");
this.arg = arg; this.op = op;
} this.arg1 = arg1;
AstVariableDefinition.prototype = Object.create(AstNode.prototype); this.arg2 = arg2;
AstVariableDefinition.prototype.visit = function (visitor) { this.min = min;
visitor.visitVariableDefinition(this); this.max = max;
}; }
function ExpressionBuilderVisitor() { visit(visitor) {
this.parts = []; visitor.visitBinaryOperation(this);
}
} }
ExpressionBuilderVisitor.prototype = {
class AstMin extends AstNode {
constructor(arg, max) {
super("max");
this.arg = arg;
this.min = arg.min;
this.max = max;
}
visit(visitor) {
visitor.visitMin(this);
}
}
class AstVariable extends AstNode {
constructor(index, min, max) {
super("var");
this.index = index;
this.min = min;
this.max = max;
}
visit(visitor) {
visitor.visitVariable(this);
}
}
class AstVariableDefinition extends AstNode {
constructor(variable, arg) {
super("definition");
this.variable = variable;
this.arg = arg;
}
visit(visitor) {
visitor.visitVariableDefinition(this);
}
}
class ExpressionBuilderVisitor {
constructor() {
this.parts = [];
}
visitArgument(arg) { visitArgument(arg) {
this.parts.push( this.parts.push(
"Math.max(", "Math.max(",
@ -1026,36 +1045,42 @@ var PostScriptCompiler = (function PostScriptCompilerClosure() {
arg.index, arg.index,
"]))" "]))"
); );
}, }
visitVariable(variable) { visitVariable(variable) {
this.parts.push("v", variable.index); this.parts.push("v", variable.index);
}, }
visitLiteral(literal) { visitLiteral(literal) {
this.parts.push(literal.number); this.parts.push(literal.number);
}, }
visitBinaryOperation(operation) { visitBinaryOperation(operation) {
this.parts.push("("); this.parts.push("(");
operation.arg1.visit(this); operation.arg1.visit(this);
this.parts.push(" ", operation.op, " "); this.parts.push(" ", operation.op, " ");
operation.arg2.visit(this); operation.arg2.visit(this);
this.parts.push(")"); this.parts.push(")");
}, }
visitVariableDefinition(definition) { visitVariableDefinition(definition) {
this.parts.push("var "); this.parts.push("var ");
definition.variable.visit(this); definition.variable.visit(this);
this.parts.push(" = "); this.parts.push(" = ");
definition.arg.visit(this); definition.arg.visit(this);
this.parts.push(";"); this.parts.push(";");
}, }
visitMin(max) { visitMin(max) {
this.parts.push("Math.min("); this.parts.push("Math.min(");
max.arg.visit(this); max.arg.visit(this);
this.parts.push(", ", max.max, ")"); this.parts.push(", ", max.max, ")");
}, }
toString() { toString() {
return this.parts.join(""); return this.parts.join("");
}, }
}; }
function buildAddOperation(num1, num2) { function buildAddOperation(num1, num2) {
if (num2.type === "literal" && num2.number === 0) { if (num2.type === "literal" && num2.number === 0) {
@ -1156,9 +1181,8 @@ var PostScriptCompiler = (function PostScriptCompilerClosure() {
} }
// eslint-disable-next-line no-shadow // eslint-disable-next-line no-shadow
function PostScriptCompiler() {} class PostScriptCompiler {
PostScriptCompiler.prototype = { compile(code, domain, range) {
compile: function PostScriptCompiler_compile(code, domain, range) {
var stack = []; var stack = [];
var instructions = []; var instructions = [];
var inputSize = domain.length >> 1, var inputSize = domain.length >> 1,
@ -1337,8 +1361,8 @@ var PostScriptCompiler = (function PostScriptCompilerClosure() {
result.push(out.join("")); result.push(out.join(""));
}); });
return result.join("\n"); return result.join("\n");
}, }
}; }
return PostScriptCompiler; return PostScriptCompiler;
})(); })();