|
|
@ -72,11 +72,12 @@ var Obj = (function() { |
|
|
|
]; |
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < types.length; ++i) { |
|
|
|
for (var i = 0; i < types.length; ++i) { |
|
|
|
var typeName = types[i]; |
|
|
|
let type = i; |
|
|
|
constructor[typeName] = i; |
|
|
|
var typeName = types[type]; |
|
|
|
|
|
|
|
constructor[typeName] = type; |
|
|
|
constructor.prototype["is" + typeName] = |
|
|
|
constructor.prototype["is" + typeName] = |
|
|
|
(function (value) { |
|
|
|
(function (value) { |
|
|
|
return this.type == i && |
|
|
|
return this.type == type && |
|
|
|
(typeof value == "undefined" || value == this.value); |
|
|
|
(typeof value == "undefined" || value == this.value); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
@ -626,3 +627,262 @@ var PDFDoc = (function () { |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
})(); |
|
|
|
})(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var Interpreter = (function() { |
|
|
|
|
|
|
|
function constructor(xref, resources, catalog, graphics) { |
|
|
|
|
|
|
|
this.xref = xref; |
|
|
|
|
|
|
|
this.resStack = [ resources ]; |
|
|
|
|
|
|
|
this.catalog = catalog; |
|
|
|
|
|
|
|
this.gfx = graphics; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const MAX_ARGS = 33; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor.prototype = { |
|
|
|
|
|
|
|
interpret: function(obj) { |
|
|
|
|
|
|
|
return this.interpretHelper(new Parser(new Lexer(obj), true)); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
interpretHelper: function(parser) { |
|
|
|
|
|
|
|
var args = [ ]; |
|
|
|
|
|
|
|
var obj; |
|
|
|
|
|
|
|
while (!((obj = parser.getObj()).isEOF())) { |
|
|
|
|
|
|
|
if (obj.isCmd()) { |
|
|
|
|
|
|
|
this.dispatch(obj, args); |
|
|
|
|
|
|
|
args = [ ]; // yuck
|
|
|
|
|
|
|
|
} else if (MAX_ARGS == args.length) { |
|
|
|
|
|
|
|
this.error("Too many arguments"); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
args.push(obj); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dispatch: function(cmdObj, args) { |
|
|
|
|
|
|
|
this.getAndCheckCmd(cmdObj, args).apply( |
|
|
|
|
|
|
|
this, args.map(function(o) o.value)); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
getAndCheckCmd: function(cmdObj, args) { |
|
|
|
|
|
|
|
const CMD_TABLE = { |
|
|
|
|
|
|
|
// Text commands
|
|
|
|
|
|
|
|
"BT": { fn: "beginText", |
|
|
|
|
|
|
|
params: [ ] }, |
|
|
|
|
|
|
|
"ET": { fn: "endText", |
|
|
|
|
|
|
|
params: [ ] }, |
|
|
|
|
|
|
|
"Td": { fn: "moveText", |
|
|
|
|
|
|
|
params: [ "Num", "Num" ] }, |
|
|
|
|
|
|
|
"Tf": { fn: "setFont", |
|
|
|
|
|
|
|
params: [ "Name", "Num" ] }, |
|
|
|
|
|
|
|
"Tj": { fn: "showText", |
|
|
|
|
|
|
|
params: [ "String" ] }, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var cmdName = cmdObj.value |
|
|
|
|
|
|
|
var cmd = CMD_TABLE[cmdName]; |
|
|
|
|
|
|
|
if (!cmd) { |
|
|
|
|
|
|
|
this.error("Unknown command '"+ cmdName +"'"); |
|
|
|
|
|
|
|
} else if (!this.typeCheck(cmd, args)) { |
|
|
|
|
|
|
|
this.error("Wrong arguments for command '"+ cmdName +"'"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return this[cmd.fn]; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
typeCheck: function(cmd, args) { |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Text commands
|
|
|
|
|
|
|
|
beginText: function() { |
|
|
|
|
|
|
|
this.gfx.beginText(); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
endText: function() { |
|
|
|
|
|
|
|
this.gfx.endText(); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
moveText: function(x, y) { |
|
|
|
|
|
|
|
this.gfx.moveText(x, y); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
setFont: function(font, size) { |
|
|
|
|
|
|
|
// lookup font
|
|
|
|
|
|
|
|
this.gfx.setFont(font, size); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
showText: function(text) { |
|
|
|
|
|
|
|
this.gfx.showText(text); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return constructor; |
|
|
|
|
|
|
|
})(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var EchoGraphics = (function() { |
|
|
|
|
|
|
|
function constructor() { |
|
|
|
|
|
|
|
this.out = ""; |
|
|
|
|
|
|
|
this.indentation = 0; |
|
|
|
|
|
|
|
this.indentationStr = ""; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor.prototype = { |
|
|
|
|
|
|
|
// Graphics state
|
|
|
|
|
|
|
|
save: function() { |
|
|
|
|
|
|
|
this.printdentln("q"); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
restore: function() { |
|
|
|
|
|
|
|
this.printdentln("Q"); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Text
|
|
|
|
|
|
|
|
beginText: function() { |
|
|
|
|
|
|
|
this.printdentln("BT"); |
|
|
|
|
|
|
|
this.indent(); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
setFont: function(font, sizePt) { |
|
|
|
|
|
|
|
this.printdentln("/"+ font +" "+ sizePt +" Tf"); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
moveText: function (x, y) { |
|
|
|
|
|
|
|
this.printdentln(""+ x +" "+ y +" Td"); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
showText: function(text) { |
|
|
|
|
|
|
|
this.printdentln("( "+ text +" ) Tj"); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
endText: function() { |
|
|
|
|
|
|
|
this.dedent(); |
|
|
|
|
|
|
|
this.printdentln("ET"); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Output state
|
|
|
|
|
|
|
|
print: function(str) { |
|
|
|
|
|
|
|
this.out += str; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
println: function(str) { |
|
|
|
|
|
|
|
this.print(str); |
|
|
|
|
|
|
|
this.out += "\n"; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
printdentln: function(str) { |
|
|
|
|
|
|
|
this.print(this.indentationStr); |
|
|
|
|
|
|
|
this.println(str); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
indent: function() { |
|
|
|
|
|
|
|
this.indentation += 2; |
|
|
|
|
|
|
|
this.indentationStr += " "; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
dedent: function() { |
|
|
|
|
|
|
|
this.indentation -= 2; |
|
|
|
|
|
|
|
this.indentationStr = this.indentationStr.slice(0, -2); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return constructor; |
|
|
|
|
|
|
|
})(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var CanvasGraphicsState = (function() { |
|
|
|
|
|
|
|
function constructor(canvasCtx, hdpi, vdpi, pageBox) { |
|
|
|
|
|
|
|
// XXX canvas2d context has much of this; need to fill in what
|
|
|
|
|
|
|
|
// canvas state doesn't store.
|
|
|
|
|
|
|
|
this.ctx = canvasCtx; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Page state
|
|
|
|
|
|
|
|
this.hdpi = hdpi |
|
|
|
|
|
|
|
this.vdpi = vdpi |
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
// Fill state
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
// Stroke state
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
// Line state
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
// Text state
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
// Current path
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
// Transforms
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
// Clipping
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor.prototype = { |
|
|
|
|
|
|
|
// Coordinate transforms
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
// CTM mutators
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
// Path mutators
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return constructor; |
|
|
|
|
|
|
|
})(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var CanvasGraphics = (function() { |
|
|
|
|
|
|
|
function constructor(canvasCtx, hdpi, vdpi, pageBox) { |
|
|
|
|
|
|
|
this.ctx = canvasCtx; |
|
|
|
|
|
|
|
this.current = new CanvasGraphicsState(this.ctx, hdpi, vdpi, pageBox); |
|
|
|
|
|
|
|
this.stateStack = [ ]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor.prototype = { |
|
|
|
|
|
|
|
save: function() { |
|
|
|
|
|
|
|
this.ctx.save(); |
|
|
|
|
|
|
|
this.stateStack.push(this.current); |
|
|
|
|
|
|
|
// ????
|
|
|
|
|
|
|
|
this.current = new CanvasGraphicsState(this.ctx, |
|
|
|
|
|
|
|
hdpi, vdpi, pageBox); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
restore: function() { |
|
|
|
|
|
|
|
this.current = this.stateStack.pop(); |
|
|
|
|
|
|
|
this.ctx.restore(); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return constructor; |
|
|
|
|
|
|
|
})(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//var PostscriptGraphics
|
|
|
|
|
|
|
|
//var SVGGraphics
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// XXX temporary testing code
|
|
|
|
|
|
|
|
var MockParser = (function() { |
|
|
|
|
|
|
|
function constructor(objs) { |
|
|
|
|
|
|
|
this.objs = objs; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor.prototype = { |
|
|
|
|
|
|
|
getObj: function() { |
|
|
|
|
|
|
|
return this.objs.shift(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return constructor; |
|
|
|
|
|
|
|
})(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function runEchoTests() { |
|
|
|
|
|
|
|
function cmd(c) { return new Obj(Obj.Cmd, c); } |
|
|
|
|
|
|
|
function name(n) { return new Obj(Obj.Name, n); } |
|
|
|
|
|
|
|
function int(i) { return new Obj(Obj.Int, i); } |
|
|
|
|
|
|
|
function string(s) { return new Obj(Obj.String, s); } |
|
|
|
|
|
|
|
function eof() { return new Obj(Obj.EOF); } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var tests = [ |
|
|
|
|
|
|
|
{ name: "Hello world", |
|
|
|
|
|
|
|
objs: [ |
|
|
|
|
|
|
|
cmd("BT"), |
|
|
|
|
|
|
|
name("F1"), int(24), cmd("Tf"), |
|
|
|
|
|
|
|
int(100), int(100), cmd("Td"), |
|
|
|
|
|
|
|
string("Hello World"), cmd("Tj"), |
|
|
|
|
|
|
|
cmd("ET"), |
|
|
|
|
|
|
|
eof() |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests.forEach(function(test) { |
|
|
|
|
|
|
|
putstr("Running echo test '"+ test.name +"'... "); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var output = ""; |
|
|
|
|
|
|
|
var gfx = new EchoGraphics(output); |
|
|
|
|
|
|
|
var i = new Interpreter(null, null, null, gfx); |
|
|
|
|
|
|
|
i.interpretHelper(new MockParser(test.objs)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print("done. Output:"); |
|
|
|
|
|
|
|
print(gfx.out); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
runEchoTests(); |
|
|
|