Index: web/client/scripts/draw.js =================================================================== --- web/client/scripts/draw.js (nonexistent) +++ web/client/scripts/draw.js (revision 5211) @@ -0,0 +1,124 @@ + +var GC_MAX_COUNT = 32; + +/** + * Constructs a graphic engine that processes graphic commands. + + * @param options.comm - communication interface + * @param options.canvas - HTML canvas rendering context + * @param options.colors - color chart for symbolic color names + */ +function GraphicEngine(options) { + this.options = Object.assign({}, options); + this.comm = options.comm; + this.canvas = options.canvas; + this.colors = options.colors; + + this.canvas.imageSmoothingEnabled = false; + + this.GCs = new Array(GC_MAX_COUNT); + this.gc = undefined; +} +GraphicEngine.prototype.onMessage = function (command, args) { + try { + switch (command) { + case "line": this.line(args[0], args[1], args[2], args[3], args[4]); + return; + + case "clr": this.setColor(args[0], args[1]); return; + case "setXorState": this.setXor(args[0], args[1]); return; + + case "makeGC": this.makeGC(); return; + case "delGC": this.deleteGC(args[0]); return; + case "ready": this.ready(); return; + } + } catch (e) { + } +} +GraphicEngine.prototype.line = function (gci, x1, y1, x2, y2) { + this.selectGC(gci); + this.canvas.moveTo(x1, y1); + this.canvas.lineTo(x2, y2); +} +GraphicEngine.prototype.selectGC = function (gci) { + if (this.gc && this.gc.gci === gci) + return; + + let gc = this.GCs[gci]; + if (!gc) { + this.comm.error("invalid GC index"); + throw new Error("invalid GC index"); + } + this.gc = gc; + + // set all drawing properties in advance + // it can be costly so optimization may be necessary + let canvas = this.canvas; + canvas.fillStyle = gc.color; + canvas.strokeStyle = gc.color; + canvas.lineWidth = gc.lineWidth; +} +GraphicEngine.prototype.makeGC = function () { + for (var i = 1; i < GC_MAX_COUNT; ++i) { + if (!this.GCs[i]) { + this.GCs[i] = { + gci: i, + color: 0, + lineWidth: 1 + }; + this.comm.send("MadeGC", [i]); + return; + } + } + this.comm.error("too many GC"); +} +GraphicEngine.prototype.deleteGC = function (gci) { + if (!this.GCs[gci]) { + this.comm.error("undefined GC"); + return; + } + this.GCs[gci] = undefined; +} +GraphicEngine.prototype.ready = function () { + this.comm.send("Ready", []); +} +GraphicEngine.prototype.setColor = function (gci, color) { + gc = this.GCs[gci]; + if (!gc) { + this.comm.error("invalid GC"); + return; + } + if (typeof color === "string" && color[0] !== '#') { + color = this.colors[color]; + if (color == null) { + this.comm.error("undefied color"); + return; + } + } + + gc.color = color; + if (this.gc == gc) { + this.canvas.fillStyle = color; + this.canvas.strokeStyle = color; + } +} +GraphicEngine.prototype.setCap = function (gci, cap) { + gc = this.GCs[gci]; + if (!gc) { + this.comm.error("invalid GC"); + return; + } + gc.cap = cap; + if (this.gc == gc) { + } +} +GraphicEngine.prototype.setXor = function (gci, state) { + gc = this.GCs[gci]; + if (!gc) { + this.comm.error("invalid GC"); + return; + } + gc.xor = state != 0; + if (this.gc == gc) { + } +}