kei-lisp-plugin-graphics 1.0.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -1
- package/dist/index.cjs +453 -409
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +77 -61
- package/dist/index.d.ts +77 -61
- package/dist/index.js +453 -409
- package/dist/index.js.map +1 -1
- package/package.json +10 -8
package/dist/index.cjs
CHANGED
|
@@ -5,7 +5,7 @@ let kei_lisp = require("kei-lisp");
|
|
|
5
5
|
* @class
|
|
6
6
|
* @classdesc Canvas2D drawing plugin for the kei-lisp interpreter. Implements
|
|
7
7
|
* the `KeiLispPlugin` contract (`name` / `has` / `apply`) and
|
|
8
|
-
* exposes
|
|
8
|
+
* exposes 45 `g…` Lisp functions that proxy to a 2D rendering
|
|
9
9
|
* context.
|
|
10
10
|
* @author Keisuke Ikeda
|
|
11
11
|
* @this {GraphicsPlugin}
|
|
@@ -17,6 +17,59 @@ var GraphicsPlugin = class GraphicsPlugin extends Object {
|
|
|
17
17
|
*/
|
|
18
18
|
static buildInFunctions = GraphicsPlugin.setup();
|
|
19
19
|
/**
|
|
20
|
+
* Builds the dispatch table.
|
|
21
|
+
* @return the dispatch table
|
|
22
|
+
*/
|
|
23
|
+
static setup() {
|
|
24
|
+
const aTable = /* @__PURE__ */ new Map();
|
|
25
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("galpha"), "gAlpha");
|
|
26
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("garc"), "gArc");
|
|
27
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("garc-to"), "gArcTo");
|
|
28
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gbezcurve-to"), "gBezCurveTo");
|
|
29
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gclear"), "gClear");
|
|
30
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gclose"), "gClose");
|
|
31
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gcolor"), "gColor");
|
|
32
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gfill"), "gFill");
|
|
33
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gfill-color"), "gFillColor");
|
|
34
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gfill-rect"), "gFillRect");
|
|
35
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gfill-text"), "gFillText");
|
|
36
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gfill-tri"), "gFillTri");
|
|
37
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gfinish-path"), "gFinishPath");
|
|
38
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gimage"), "gImage");
|
|
39
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gmove-to"), "gMoveTo");
|
|
40
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gline-to"), "gLineTo");
|
|
41
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gline-cap"), "gLineCap");
|
|
42
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gline-join"), "gLineJoin");
|
|
43
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gline-width"), "gLineWidth");
|
|
44
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gopen"), "gOpen");
|
|
45
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gpattern"), "gPattern");
|
|
46
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gquadcurve-to"), "gQuadCurveTo");
|
|
47
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gsave-jpeg"), "gSaveJpeg");
|
|
48
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gsave-png"), "gSavePng");
|
|
49
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gscale"), "gScale");
|
|
50
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gshadow-blur"), "gShadowBlur");
|
|
51
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gshadow-color"), "gShadowColor");
|
|
52
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gshadow-offsetx"), "gShadowOffsetX");
|
|
53
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gshadow-offsety"), "gShadowOffsetY");
|
|
54
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gsleep"), "gSleep");
|
|
55
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gstart-path"), "gStartPath");
|
|
56
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gstroke"), "gStroke");
|
|
57
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gstroke-color"), "gStrokeColor");
|
|
58
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gstroke-rect"), "gStrokeRect");
|
|
59
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gstroke-text"), "gStrokeText");
|
|
60
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gstroke-tri"), "gStrokeTri");
|
|
61
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gtext-align"), "gTextAlign");
|
|
62
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gtext-dire"), "gTextDirection");
|
|
63
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gtext-font"), "gTextFont");
|
|
64
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gtext-line"), "gTextBaseline");
|
|
65
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gtranslate"), "gTranslate");
|
|
66
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("grect"), "gRect");
|
|
67
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("grotate"), "gRotate");
|
|
68
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("gsave"), "gSave");
|
|
69
|
+
aTable.set(kei_lisp.InterpretedSymbol.of("grestore"), "gRestore");
|
|
70
|
+
return aTable;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
20
73
|
* Plugin identifier, used for diagnostics.
|
|
21
74
|
*/
|
|
22
75
|
name = "graphics";
|
|
@@ -35,6 +88,79 @@ var GraphicsPlugin = class GraphicsPlugin extends Object {
|
|
|
35
88
|
this.isOpen = false;
|
|
36
89
|
}
|
|
37
90
|
/**
|
|
91
|
+
* Writes a diagnostic line directly to `process.stderr`, matching the
|
|
92
|
+
* convention used by kei-lisp itself (`Applier.format` writes to
|
|
93
|
+
* `process.stdout`). In a Node runtime this hits the real stderr; in a
|
|
94
|
+
* browser kei-lisp host (e.g. kei-lisp-web) the host typically swaps
|
|
95
|
+
* `process.stderr.write` for a sink that routes to the REPL output panel,
|
|
96
|
+
* so the same call reaches the user via the host's normal output channel.
|
|
97
|
+
* @param line - the line to write
|
|
98
|
+
*/
|
|
99
|
+
#print(line) {
|
|
100
|
+
process.stderr.write(line + "\n");
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Encodes the canvas via `toDataURL` and triggers a browser download through
|
|
104
|
+
* a temporary `<a download>` element. Requires a DOM (`document`) and an
|
|
105
|
+
* `HTMLCanvasElement`; `OffscreenCanvas` has no `toDataURL`, and Node.js has
|
|
106
|
+
* no `document` — those callers must pass a file path instead.
|
|
107
|
+
* @param mimeType - the image MIME type to encode
|
|
108
|
+
* @param label - the format name used in diagnostics ("jpeg" / "png")
|
|
109
|
+
* @return `t` on success, `Cons.nil` otherwise
|
|
110
|
+
*/
|
|
111
|
+
#downloadCanvas(mimeType, label) {
|
|
112
|
+
if (typeof document === "undefined" || !("toDataURL" in this.canvas)) {
|
|
113
|
+
this.#print(`Can not save ${label}. Browser download needs a DOM and an HTMLCanvasElement; pass a file path to save on Node.js.`);
|
|
114
|
+
return kei_lisp.Cons.nil;
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const link = document.createElement("a");
|
|
118
|
+
link.href = this.canvas.toDataURL(mimeType);
|
|
119
|
+
link.download = "canvas";
|
|
120
|
+
document.body.append(link);
|
|
121
|
+
link.click();
|
|
122
|
+
link.remove();
|
|
123
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
124
|
+
} catch {
|
|
125
|
+
this.#print(`Can not save ${label}. If you are using an image in the canvas, you can't save ${label}.`);
|
|
126
|
+
return kei_lisp.Cons.nil;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Writes the encoded canvas image to a file path on Node.js, using
|
|
131
|
+
* `process.getBuiltinModule('node:fs')` so browser bundles never see a
|
|
132
|
+
* `node:fs` import. `HTMLCanvasElement` (and node-canvas) encode
|
|
133
|
+
* synchronously via `toDataURL`; `OffscreenCanvas` only offers the async
|
|
134
|
+
* `convertToBlob`, so its file is written after this returns — the same
|
|
135
|
+
* fire-and-forget contract as `gImage`.
|
|
136
|
+
* @param path - the destination file path
|
|
137
|
+
* @param mimeType - the image MIME type to encode
|
|
138
|
+
* @param label - the format name used in diagnostics ("jpeg" / "png")
|
|
139
|
+
* @return `t` on success, `Cons.nil` otherwise
|
|
140
|
+
*/
|
|
141
|
+
#writeCanvasToFile(path, mimeType, label) {
|
|
142
|
+
const fs = typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("node:fs") : void 0;
|
|
143
|
+
if (fs === void 0) {
|
|
144
|
+
this.#print(`Can not save ${label}. Saving to a file path requires Node.js.`);
|
|
145
|
+
return kei_lisp.Cons.nil;
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
if ("toDataURL" in this.canvas) {
|
|
149
|
+
const dataUrl = this.canvas.toDataURL(mimeType);
|
|
150
|
+
const base64 = dataUrl.slice(dataUrl.indexOf(",") + 1);
|
|
151
|
+
fs.writeFileSync(path, Buffer.from(base64, "base64"));
|
|
152
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
153
|
+
}
|
|
154
|
+
this.canvas.convertToBlob({ type: mimeType }).then(async (blob) => {
|
|
155
|
+
fs.writeFileSync(path, new Uint8Array(await blob.arrayBuffer()));
|
|
156
|
+
});
|
|
157
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
158
|
+
} catch {
|
|
159
|
+
this.#print(`Can not save ${label}.`);
|
|
160
|
+
return kei_lisp.Cons.nil;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
38
164
|
* Returns true if this plugin handles the given symbol.
|
|
39
165
|
* @param aSymbol - the call symbol
|
|
40
166
|
* @return true if `apply` should be called
|
|
@@ -45,22 +171,22 @@ var GraphicsPlugin = class GraphicsPlugin extends Object {
|
|
|
45
171
|
/**
|
|
46
172
|
* Dispatches the given symbol to the matching `g…` method.
|
|
47
173
|
* @param aSymbol - the call symbol
|
|
48
|
-
* @param
|
|
49
|
-
* @param
|
|
174
|
+
* @param arguments_ - the evaluated argument list
|
|
175
|
+
* @param _context - the interpreter context (unused by this plugin)
|
|
50
176
|
* @return the method's result, or `Cons.nil` if dispatch fails
|
|
51
177
|
*/
|
|
52
|
-
apply(aSymbol,
|
|
53
|
-
return this.selectProcedure(aSymbol,
|
|
178
|
+
apply(aSymbol, arguments_, _context) {
|
|
179
|
+
return this.selectProcedure(aSymbol, arguments_);
|
|
54
180
|
}
|
|
55
181
|
/**
|
|
56
182
|
* Resolves the procedure name and invokes the matching method.
|
|
57
183
|
* @param procedure - the Lisp symbol
|
|
58
|
-
* @param
|
|
184
|
+
* @param arguments_ - the evaluated argument list
|
|
59
185
|
* @return the method's result, or `Cons.nil` if not registered
|
|
60
186
|
*/
|
|
61
|
-
selectProcedure(procedure,
|
|
62
|
-
if (GraphicsPlugin.buildInFunctions.has(procedure)) return this.buildInFunction(procedure,
|
|
63
|
-
this
|
|
187
|
+
selectProcedure(procedure, arguments_) {
|
|
188
|
+
if (GraphicsPlugin.buildInFunctions.has(procedure)) return this.buildInFunction(procedure, arguments_);
|
|
189
|
+
this.#print(`I could find no procedure description for ${String(procedure)}`);
|
|
64
190
|
return kei_lisp.Cons.nil;
|
|
65
191
|
}
|
|
66
192
|
/**
|
|
@@ -70,14 +196,14 @@ var GraphicsPlugin = class GraphicsPlugin extends Object {
|
|
|
70
196
|
* Ramda `R.invoker(1, methodName)(args, this)` call would surface the same
|
|
71
197
|
* error by attempting to call `undefined`.
|
|
72
198
|
* @param procedure - the Lisp symbol
|
|
73
|
-
* @param
|
|
199
|
+
* @param arguments_ - the evaluated argument list
|
|
74
200
|
* @return the method's result
|
|
75
201
|
*/
|
|
76
|
-
buildInFunction(procedure,
|
|
202
|
+
buildInFunction(procedure, arguments_) {
|
|
77
203
|
const methodName = GraphicsPlugin.buildInFunctions.get(procedure);
|
|
78
204
|
const method = this[methodName];
|
|
79
205
|
if (typeof method !== "function") throw new TypeError(`${this.constructor.name} does not have a method named "${methodName}"`);
|
|
80
|
-
return method.call(this,
|
|
206
|
+
return method.call(this, arguments_);
|
|
81
207
|
}
|
|
82
208
|
/**
|
|
83
209
|
* Checks whether the canvas exposes a usable 2D context, and narrows
|
|
@@ -86,47 +212,34 @@ var GraphicsPlugin = class GraphicsPlugin extends Object {
|
|
|
86
212
|
*/
|
|
87
213
|
checkSupport() {
|
|
88
214
|
if (this.ctx === null) {
|
|
89
|
-
this
|
|
215
|
+
this.#print("Unable to initialize canvas. The browser or machine may not support it.");
|
|
90
216
|
return false;
|
|
91
217
|
}
|
|
92
218
|
return true;
|
|
93
219
|
}
|
|
94
|
-
|
|
95
|
-
* Writes a diagnostic line directly to `process.stderr`, matching the
|
|
96
|
-
* convention used by kei-lisp itself (`Applier.format` writes to
|
|
97
|
-
* `process.stdout`). In a Node runtime this hits the real stderr; in a
|
|
98
|
-
* browser kei-lisp host (e.g. kei-lisp-web) the host typically swaps
|
|
99
|
-
* `process.stderr.write` for a sink that routes to the REPL output panel,
|
|
100
|
-
* so the same call reaches the user via the host's normal output channel.
|
|
101
|
-
* @param line - the line to write
|
|
102
|
-
*/
|
|
103
|
-
_print(line) {
|
|
104
|
-
process.stderr.write(line + "\n");
|
|
105
|
-
}
|
|
106
|
-
gAlpha(args) {
|
|
220
|
+
gAlpha(arguments_) {
|
|
107
221
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
108
222
|
if (this.isOpen) try {
|
|
109
|
-
if (
|
|
110
|
-
const aNumber =
|
|
223
|
+
if (arguments_.length() === 1 && kei_lisp.Cons.isNumber(arguments_.car)) {
|
|
224
|
+
const aNumber = arguments_.car <= 0 ? 0 : arguments_.car >= 1 ? 1 : arguments_.car;
|
|
111
225
|
this.ctx.globalAlpha = aNumber;
|
|
112
|
-
this.ctx.save();
|
|
113
226
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
114
227
|
}
|
|
115
|
-
this
|
|
228
|
+
this.#print("Can not set alpha.");
|
|
116
229
|
return kei_lisp.Cons.nil;
|
|
117
230
|
} catch {
|
|
118
|
-
this
|
|
231
|
+
this.#print("Can not set alpha.");
|
|
119
232
|
return kei_lisp.Cons.nil;
|
|
120
233
|
}
|
|
121
|
-
this
|
|
234
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
122
235
|
return kei_lisp.Cons.nil;
|
|
123
236
|
}
|
|
124
|
-
gArc(
|
|
237
|
+
gArc(arguments_) {
|
|
125
238
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
126
239
|
if (this.isOpen) try {
|
|
127
|
-
if (
|
|
128
|
-
const a0 =
|
|
129
|
-
const cdr1 =
|
|
240
|
+
if (arguments_.length() === 6) {
|
|
241
|
+
const a0 = arguments_.car;
|
|
242
|
+
const cdr1 = arguments_.cdr;
|
|
130
243
|
const a1 = cdr1.car;
|
|
131
244
|
const cdr2 = cdr1.cdr;
|
|
132
245
|
const a2 = cdr2.car;
|
|
@@ -136,27 +249,26 @@ var GraphicsPlugin = class GraphicsPlugin extends Object {
|
|
|
136
249
|
const a4 = cdr4.car;
|
|
137
250
|
const a5 = cdr4.cdr.car;
|
|
138
251
|
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2) && kei_lisp.Cons.isNumber(a3) && kei_lisp.Cons.isNumber(a4) && kei_lisp.Cons.isNumber(a5)) {
|
|
139
|
-
const
|
|
140
|
-
this.ctx.arc(a0, a1, a2, Math.PI / 180 * a3, Math.PI / 180 * a4,
|
|
141
|
-
this.ctx.save();
|
|
252
|
+
const isAFlag = a5 >= 0;
|
|
253
|
+
this.ctx.arc(a0, a1, a2, Math.PI / 180 * a3, Math.PI / 180 * a4, isAFlag);
|
|
142
254
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
143
255
|
}
|
|
144
256
|
}
|
|
145
|
-
this
|
|
257
|
+
this.#print("Can not draw arc.");
|
|
146
258
|
return kei_lisp.Cons.nil;
|
|
147
259
|
} catch {
|
|
148
|
-
this
|
|
260
|
+
this.#print("Can not draw arc.");
|
|
149
261
|
return kei_lisp.Cons.nil;
|
|
150
262
|
}
|
|
151
|
-
this
|
|
263
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
152
264
|
return kei_lisp.Cons.nil;
|
|
153
265
|
}
|
|
154
|
-
gArcTo(
|
|
266
|
+
gArcTo(arguments_) {
|
|
155
267
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
156
268
|
if (this.isOpen) try {
|
|
157
|
-
if (
|
|
158
|
-
const a0 =
|
|
159
|
-
const cdr1 =
|
|
269
|
+
if (arguments_.length() === 5) {
|
|
270
|
+
const a0 = arguments_.car;
|
|
271
|
+
const cdr1 = arguments_.cdr;
|
|
160
272
|
const a1 = cdr1.car;
|
|
161
273
|
const cdr2 = cdr1.cdr;
|
|
162
274
|
const a2 = cdr2.car;
|
|
@@ -165,25 +277,24 @@ var GraphicsPlugin = class GraphicsPlugin extends Object {
|
|
|
165
277
|
const a4 = cdr3.cdr.car;
|
|
166
278
|
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2) && kei_lisp.Cons.isNumber(a3) && kei_lisp.Cons.isNumber(a4)) {
|
|
167
279
|
this.ctx.arcTo(a0, a1, a2, a3, a4);
|
|
168
|
-
this.ctx.save();
|
|
169
280
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
170
281
|
}
|
|
171
282
|
}
|
|
172
|
-
this
|
|
283
|
+
this.#print("Can not draw arc to.");
|
|
173
284
|
return kei_lisp.Cons.nil;
|
|
174
285
|
} catch {
|
|
175
|
-
this
|
|
286
|
+
this.#print("Can not draw arc to.");
|
|
176
287
|
return kei_lisp.Cons.nil;
|
|
177
288
|
}
|
|
178
|
-
this
|
|
289
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
179
290
|
return kei_lisp.Cons.nil;
|
|
180
291
|
}
|
|
181
|
-
gBezCurveTo(
|
|
292
|
+
gBezCurveTo(arguments_) {
|
|
182
293
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
183
294
|
if (this.isOpen) try {
|
|
184
|
-
if (
|
|
185
|
-
const a0 =
|
|
186
|
-
const cdr1 =
|
|
295
|
+
if (arguments_.length() === 6) {
|
|
296
|
+
const a0 = arguments_.car;
|
|
297
|
+
const cdr1 = arguments_.cdr;
|
|
187
298
|
const a1 = cdr1.car;
|
|
188
299
|
const cdr2 = cdr1.cdr;
|
|
189
300
|
const a2 = cdr2.car;
|
|
@@ -194,17 +305,16 @@ var GraphicsPlugin = class GraphicsPlugin extends Object {
|
|
|
194
305
|
const a5 = cdr4.cdr.car;
|
|
195
306
|
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2) && kei_lisp.Cons.isNumber(a3) && kei_lisp.Cons.isNumber(a4) && kei_lisp.Cons.isNumber(a5)) {
|
|
196
307
|
this.ctx.bezierCurveTo(a0, a1, a2, a3, a4, a5);
|
|
197
|
-
this.ctx.save();
|
|
198
308
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
199
309
|
}
|
|
200
310
|
}
|
|
201
|
-
this
|
|
311
|
+
this.#print("Can not draw bezier curve.");
|
|
202
312
|
return kei_lisp.Cons.nil;
|
|
203
313
|
} catch {
|
|
204
|
-
this
|
|
314
|
+
this.#print("Can not draw bezier curve.");
|
|
205
315
|
return kei_lisp.Cons.nil;
|
|
206
316
|
}
|
|
207
|
-
this
|
|
317
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
208
318
|
return kei_lisp.Cons.nil;
|
|
209
319
|
}
|
|
210
320
|
gClear() {
|
|
@@ -213,13 +323,12 @@ var GraphicsPlugin = class GraphicsPlugin extends Object {
|
|
|
213
323
|
this.ctx.fillStyle = "#ffffff";
|
|
214
324
|
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
|
215
325
|
this.ctx.fillStyle = "#000000";
|
|
216
|
-
this.ctx.save();
|
|
217
326
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
218
327
|
} catch {
|
|
219
|
-
this
|
|
328
|
+
this.#print("Can not clear.");
|
|
220
329
|
return kei_lisp.Cons.nil;
|
|
221
330
|
}
|
|
222
|
-
this
|
|
331
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
223
332
|
return kei_lisp.Cons.nil;
|
|
224
333
|
}
|
|
225
334
|
gClose() {
|
|
@@ -229,116 +338,111 @@ var GraphicsPlugin = class GraphicsPlugin extends Object {
|
|
|
229
338
|
this.isOpen = false;
|
|
230
339
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
231
340
|
} catch {
|
|
232
|
-
this
|
|
341
|
+
this.#print("Can not close.");
|
|
233
342
|
return kei_lisp.Cons.nil;
|
|
234
343
|
}
|
|
235
|
-
this
|
|
344
|
+
this.#print("The canvas has already been closed.");
|
|
236
345
|
return kei_lisp.Cons.nil;
|
|
237
346
|
}
|
|
238
|
-
gColor(
|
|
347
|
+
gColor(arguments_) {
|
|
239
348
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
240
349
|
if (this.isOpen) try {
|
|
241
|
-
if (
|
|
242
|
-
const aColor = this.selectColor(
|
|
350
|
+
if (arguments_.length() >= 1) {
|
|
351
|
+
const aColor = this.selectColor(arguments_);
|
|
243
352
|
this.ctx.fillStyle = aColor;
|
|
244
353
|
this.ctx.strokeStyle = aColor;
|
|
245
|
-
this.ctx.save();
|
|
246
354
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
247
355
|
}
|
|
248
|
-
this
|
|
356
|
+
this.#print("Can not set color.");
|
|
249
357
|
return kei_lisp.Cons.nil;
|
|
250
358
|
} catch {
|
|
251
|
-
this
|
|
359
|
+
this.#print("Can not set color.");
|
|
252
360
|
return kei_lisp.Cons.nil;
|
|
253
361
|
}
|
|
254
|
-
this
|
|
362
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
255
363
|
return kei_lisp.Cons.nil;
|
|
256
364
|
}
|
|
257
365
|
gFill() {
|
|
258
366
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
259
367
|
if (this.isOpen) try {
|
|
260
368
|
this.ctx.fill();
|
|
261
|
-
this.ctx.save();
|
|
262
369
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
263
370
|
} catch {
|
|
264
|
-
this
|
|
371
|
+
this.#print("Can not fill.");
|
|
265
372
|
return kei_lisp.Cons.nil;
|
|
266
373
|
}
|
|
267
|
-
this
|
|
374
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
268
375
|
return kei_lisp.Cons.nil;
|
|
269
376
|
}
|
|
270
|
-
gFillColor(
|
|
377
|
+
gFillColor(arguments_) {
|
|
271
378
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
272
379
|
if (this.isOpen) try {
|
|
273
|
-
if (
|
|
274
|
-
const aColor = this.selectColor(
|
|
380
|
+
if (arguments_.length() >= 1) {
|
|
381
|
+
const aColor = this.selectColor(arguments_);
|
|
275
382
|
this.ctx.fillStyle = aColor;
|
|
276
|
-
this.ctx.save();
|
|
277
383
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
278
384
|
}
|
|
279
|
-
this
|
|
385
|
+
this.#print("Can not set fill color.");
|
|
280
386
|
return kei_lisp.Cons.nil;
|
|
281
387
|
} catch {
|
|
282
|
-
this
|
|
388
|
+
this.#print("Can not set fill color.");
|
|
283
389
|
return kei_lisp.Cons.nil;
|
|
284
390
|
}
|
|
285
|
-
this
|
|
391
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
286
392
|
return kei_lisp.Cons.nil;
|
|
287
393
|
}
|
|
288
|
-
gFillRect(
|
|
394
|
+
gFillRect(arguments_) {
|
|
289
395
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
290
396
|
if (this.isOpen) try {
|
|
291
|
-
if (
|
|
292
|
-
const a0 =
|
|
293
|
-
const cdr1 =
|
|
397
|
+
if (arguments_.length() === 4) {
|
|
398
|
+
const a0 = arguments_.car;
|
|
399
|
+
const cdr1 = arguments_.cdr;
|
|
294
400
|
const a1 = cdr1.car;
|
|
295
401
|
const cdr2 = cdr1.cdr;
|
|
296
402
|
const a2 = cdr2.car;
|
|
297
403
|
const a3 = cdr2.cdr.car;
|
|
298
404
|
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2) && kei_lisp.Cons.isNumber(a3)) {
|
|
299
405
|
this.ctx.fillRect(a0, a1, a2, a3);
|
|
300
|
-
this.ctx.save();
|
|
301
406
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
302
407
|
}
|
|
303
408
|
}
|
|
304
|
-
this
|
|
409
|
+
this.#print("Can not draw fill rectangle.");
|
|
305
410
|
return kei_lisp.Cons.nil;
|
|
306
411
|
} catch {
|
|
307
|
-
this
|
|
412
|
+
this.#print("Can not draw fill rectangle.");
|
|
308
413
|
return kei_lisp.Cons.nil;
|
|
309
414
|
}
|
|
310
|
-
this
|
|
415
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
311
416
|
return kei_lisp.Cons.nil;
|
|
312
417
|
}
|
|
313
|
-
gFillText(
|
|
418
|
+
gFillText(arguments_) {
|
|
314
419
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
315
420
|
if (this.isOpen) try {
|
|
316
|
-
if (
|
|
317
|
-
const a0 =
|
|
318
|
-
const cdr1 =
|
|
421
|
+
if (arguments_.length() === 3) {
|
|
422
|
+
const a0 = arguments_.car;
|
|
423
|
+
const cdr1 = arguments_.cdr;
|
|
319
424
|
const a1 = cdr1.car;
|
|
320
425
|
const a2 = cdr1.cdr.car;
|
|
321
426
|
if (kei_lisp.Cons.isString(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2)) {
|
|
322
427
|
this.ctx.fillText(a0, a1, a2);
|
|
323
|
-
this.ctx.save();
|
|
324
428
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
325
429
|
}
|
|
326
430
|
}
|
|
327
|
-
this
|
|
431
|
+
this.#print("Can not draw fill text.");
|
|
328
432
|
return kei_lisp.Cons.nil;
|
|
329
433
|
} catch {
|
|
330
|
-
this
|
|
434
|
+
this.#print("Can not draw fill text.");
|
|
331
435
|
return kei_lisp.Cons.nil;
|
|
332
436
|
}
|
|
333
|
-
this
|
|
437
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
334
438
|
return kei_lisp.Cons.nil;
|
|
335
439
|
}
|
|
336
|
-
gFillTri(
|
|
440
|
+
gFillTri(arguments_) {
|
|
337
441
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
338
442
|
if (this.isOpen) try {
|
|
339
|
-
if (
|
|
340
|
-
const a0 =
|
|
341
|
-
const cdr1 =
|
|
443
|
+
if (arguments_.length() === 6) {
|
|
444
|
+
const a0 = arguments_.car;
|
|
445
|
+
const cdr1 = arguments_.cdr;
|
|
342
446
|
const a1 = cdr1.car;
|
|
343
447
|
const cdr2 = cdr1.cdr;
|
|
344
448
|
const a2 = cdr2.car;
|
|
@@ -353,54 +457,51 @@ var GraphicsPlugin = class GraphicsPlugin extends Object {
|
|
|
353
457
|
this.ctx.lineTo(a2, a3);
|
|
354
458
|
this.ctx.lineTo(a4, a5);
|
|
355
459
|
this.ctx.fill();
|
|
356
|
-
this.ctx.save();
|
|
357
460
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
358
461
|
}
|
|
359
462
|
}
|
|
360
|
-
this
|
|
463
|
+
this.#print("Can not draw fill triangle.");
|
|
361
464
|
return kei_lisp.Cons.nil;
|
|
362
465
|
} catch {
|
|
363
|
-
this
|
|
466
|
+
this.#print("Can not draw fill triangle.");
|
|
364
467
|
return kei_lisp.Cons.nil;
|
|
365
468
|
}
|
|
366
|
-
this
|
|
469
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
367
470
|
return kei_lisp.Cons.nil;
|
|
368
471
|
}
|
|
369
472
|
gFinishPath() {
|
|
370
473
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
371
474
|
if (this.isOpen) try {
|
|
372
475
|
this.ctx.closePath();
|
|
373
|
-
this.ctx.save();
|
|
374
476
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
375
477
|
} catch {
|
|
376
|
-
this
|
|
478
|
+
this.#print("Can not finish path.");
|
|
377
479
|
return kei_lisp.Cons.nil;
|
|
378
480
|
}
|
|
379
|
-
this
|
|
481
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
380
482
|
return kei_lisp.Cons.nil;
|
|
381
483
|
}
|
|
382
|
-
gImage(
|
|
484
|
+
gImage(arguments_) {
|
|
383
485
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
384
486
|
if (this.isOpen) try {
|
|
385
|
-
const
|
|
386
|
-
if (
|
|
387
|
-
const a0 =
|
|
388
|
-
const cdr1 =
|
|
487
|
+
const length_ = arguments_.length();
|
|
488
|
+
if (length_ === 3) {
|
|
489
|
+
const a0 = arguments_.car;
|
|
490
|
+
const cdr1 = arguments_.cdr;
|
|
389
491
|
const a1 = cdr1.car;
|
|
390
492
|
const a2 = cdr1.cdr.car;
|
|
391
493
|
if (kei_lisp.Cons.isString(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2)) {
|
|
392
|
-
const
|
|
494
|
+
const context = this.ctx;
|
|
393
495
|
const anImage = new Image();
|
|
394
496
|
anImage.src = a0;
|
|
395
497
|
anImage.onload = () => {
|
|
396
|
-
|
|
498
|
+
context.drawImage(anImage, a1, a2);
|
|
397
499
|
};
|
|
398
|
-
ctx.save();
|
|
399
500
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
400
501
|
}
|
|
401
|
-
} else if (
|
|
402
|
-
const a0 =
|
|
403
|
-
const cdr1 =
|
|
502
|
+
} else if (length_ === 5) {
|
|
503
|
+
const a0 = arguments_.car;
|
|
504
|
+
const cdr1 = arguments_.cdr;
|
|
404
505
|
const a1 = cdr1.car;
|
|
405
506
|
const cdr2 = cdr1.cdr;
|
|
406
507
|
const a2 = cdr2.car;
|
|
@@ -408,119 +509,111 @@ var GraphicsPlugin = class GraphicsPlugin extends Object {
|
|
|
408
509
|
const a3 = cdr3.car;
|
|
409
510
|
const a4 = cdr3.cdr.car;
|
|
410
511
|
if (kei_lisp.Cons.isString(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2) && kei_lisp.Cons.isNumber(a3) && kei_lisp.Cons.isNumber(a4)) {
|
|
411
|
-
const
|
|
512
|
+
const context = this.ctx;
|
|
412
513
|
const anImage = new Image();
|
|
413
514
|
anImage.src = a0;
|
|
414
515
|
anImage.onload = () => {
|
|
415
|
-
|
|
516
|
+
context.drawImage(anImage, a1, a2, a3, a4);
|
|
416
517
|
};
|
|
417
|
-
ctx.save();
|
|
418
518
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
419
519
|
}
|
|
420
520
|
}
|
|
421
|
-
this
|
|
521
|
+
this.#print("Can not draw Image.");
|
|
422
522
|
return kei_lisp.Cons.nil;
|
|
423
523
|
} catch {
|
|
424
|
-
this
|
|
524
|
+
this.#print("Can not draw Image.");
|
|
425
525
|
return kei_lisp.Cons.nil;
|
|
426
526
|
}
|
|
427
|
-
this
|
|
527
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
428
528
|
return kei_lisp.Cons.nil;
|
|
429
529
|
}
|
|
430
|
-
gLineTo(
|
|
530
|
+
gLineTo(arguments_) {
|
|
431
531
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
432
532
|
if (this.isOpen) try {
|
|
433
|
-
if (
|
|
434
|
-
const a0 =
|
|
435
|
-
const a1 =
|
|
533
|
+
if (arguments_.length() === 2) {
|
|
534
|
+
const a0 = arguments_.car;
|
|
535
|
+
const a1 = arguments_.cdr.car;
|
|
436
536
|
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1)) {
|
|
437
537
|
this.ctx.lineTo(a0, a1);
|
|
438
|
-
this.ctx.save();
|
|
439
538
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
440
539
|
}
|
|
441
540
|
}
|
|
442
|
-
this
|
|
541
|
+
this.#print("Can not draw line to");
|
|
443
542
|
return kei_lisp.Cons.nil;
|
|
444
543
|
} catch {
|
|
445
|
-
this
|
|
544
|
+
this.#print("Can not draw line to");
|
|
446
545
|
return kei_lisp.Cons.nil;
|
|
447
546
|
}
|
|
448
|
-
this
|
|
547
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
449
548
|
return kei_lisp.Cons.nil;
|
|
450
549
|
}
|
|
451
|
-
gLineCap(
|
|
550
|
+
gLineCap(arguments_) {
|
|
452
551
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
453
552
|
if (this.isOpen) try {
|
|
454
|
-
if (
|
|
455
|
-
|
|
456
|
-
this.ctx.lineCap = aString;
|
|
457
|
-
this.ctx.save();
|
|
553
|
+
if (arguments_.length() === 1 && kei_lisp.Cons.isString(arguments_.car)) {
|
|
554
|
+
this.ctx.lineCap = arguments_.car;
|
|
458
555
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
459
556
|
}
|
|
460
|
-
this
|
|
557
|
+
this.#print("Can not set line cap.");
|
|
461
558
|
return kei_lisp.Cons.nil;
|
|
462
559
|
} catch {
|
|
463
|
-
this
|
|
560
|
+
this.#print("Can not set line cap.");
|
|
464
561
|
return kei_lisp.Cons.nil;
|
|
465
562
|
}
|
|
466
|
-
this
|
|
563
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
467
564
|
return kei_lisp.Cons.nil;
|
|
468
565
|
}
|
|
469
|
-
gLineJoin(
|
|
566
|
+
gLineJoin(arguments_) {
|
|
470
567
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
471
568
|
if (this.isOpen) try {
|
|
472
|
-
if (
|
|
473
|
-
|
|
474
|
-
this.ctx.lineJoin = aString;
|
|
475
|
-
this.ctx.save();
|
|
569
|
+
if (arguments_.length() === 1 && kei_lisp.Cons.isString(arguments_.car)) {
|
|
570
|
+
this.ctx.lineJoin = arguments_.car;
|
|
476
571
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
477
572
|
}
|
|
478
|
-
this
|
|
573
|
+
this.#print("Can not set line join.");
|
|
479
574
|
return kei_lisp.Cons.nil;
|
|
480
575
|
} catch {
|
|
481
|
-
this
|
|
576
|
+
this.#print("Can not set line join.");
|
|
482
577
|
return kei_lisp.Cons.nil;
|
|
483
578
|
}
|
|
484
|
-
this
|
|
579
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
485
580
|
return kei_lisp.Cons.nil;
|
|
486
581
|
}
|
|
487
|
-
gLineWidth(
|
|
582
|
+
gLineWidth(arguments_) {
|
|
488
583
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
489
584
|
if (this.isOpen) try {
|
|
490
|
-
if (
|
|
491
|
-
const aNumber =
|
|
585
|
+
if (arguments_.length() === 1 && kei_lisp.Cons.isNumber(arguments_.car)) {
|
|
586
|
+
const aNumber = arguments_.car <= 0 ? 1 : arguments_.car;
|
|
492
587
|
this.ctx.lineWidth = aNumber;
|
|
493
|
-
this.ctx.save();
|
|
494
588
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
495
589
|
}
|
|
496
|
-
this
|
|
590
|
+
this.#print("Can not set line width.");
|
|
497
591
|
return kei_lisp.Cons.nil;
|
|
498
592
|
} catch {
|
|
499
|
-
this
|
|
593
|
+
this.#print("Can not set line width.");
|
|
500
594
|
return kei_lisp.Cons.nil;
|
|
501
595
|
}
|
|
502
|
-
this
|
|
596
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
503
597
|
return kei_lisp.Cons.nil;
|
|
504
598
|
}
|
|
505
|
-
gMoveTo(
|
|
599
|
+
gMoveTo(arguments_) {
|
|
506
600
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
507
601
|
if (this.isOpen) try {
|
|
508
|
-
if (
|
|
509
|
-
const a0 =
|
|
510
|
-
const a1 =
|
|
602
|
+
if (arguments_.length() === 2) {
|
|
603
|
+
const a0 = arguments_.car;
|
|
604
|
+
const a1 = arguments_.cdr.car;
|
|
511
605
|
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1)) {
|
|
512
606
|
this.ctx.moveTo(a0, a1);
|
|
513
|
-
this.ctx.save();
|
|
514
607
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
515
608
|
}
|
|
516
609
|
}
|
|
517
|
-
this
|
|
610
|
+
this.#print("Can not move");
|
|
518
611
|
return kei_lisp.Cons.nil;
|
|
519
612
|
} catch {
|
|
520
|
-
this
|
|
613
|
+
this.#print("Can not move");
|
|
521
614
|
return kei_lisp.Cons.nil;
|
|
522
615
|
}
|
|
523
|
-
this
|
|
616
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
524
617
|
return kei_lisp.Cons.nil;
|
|
525
618
|
}
|
|
526
619
|
gOpen() {
|
|
@@ -530,304 +623,278 @@ var GraphicsPlugin = class GraphicsPlugin extends Object {
|
|
|
530
623
|
this.ctx.fillStyle = "#ffffff";
|
|
531
624
|
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
|
532
625
|
this.ctx.fillStyle = "#000000";
|
|
533
|
-
this.
|
|
534
|
-
this._print("canvas size, width : 600 height : 300");
|
|
626
|
+
this.#print(`canvas size, width : ${this.canvas.width} height : ${this.canvas.height}`);
|
|
535
627
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
536
628
|
} catch {
|
|
537
|
-
this
|
|
629
|
+
this.#print("Can not open.");
|
|
538
630
|
return kei_lisp.Cons.nil;
|
|
539
631
|
}
|
|
540
|
-
this
|
|
632
|
+
this.#print("The canvas has already been opened.");
|
|
541
633
|
return kei_lisp.Cons.nil;
|
|
542
634
|
}
|
|
543
|
-
gPattern(
|
|
635
|
+
gPattern(arguments_) {
|
|
544
636
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
545
637
|
if (this.isOpen) try {
|
|
546
|
-
if (
|
|
547
|
-
const a0 =
|
|
548
|
-
const a1 =
|
|
638
|
+
if (arguments_.length() === 2) {
|
|
639
|
+
const a0 = arguments_.car;
|
|
640
|
+
const a1 = arguments_.cdr.car;
|
|
549
641
|
if (kei_lisp.Cons.isString(a0) && kei_lisp.Cons.isNumber(a1)) {
|
|
550
642
|
const aString = a1 === 0 ? "repeat" : a1 > 0 ? "repeat-x" : "repeat-y";
|
|
551
|
-
const
|
|
643
|
+
const context = this.ctx;
|
|
552
644
|
const anImage = new Image();
|
|
553
645
|
anImage.src = a0;
|
|
554
646
|
anImage.onload = () => {
|
|
555
|
-
|
|
647
|
+
context.fillStyle = context.createPattern(anImage, aString);
|
|
556
648
|
};
|
|
557
|
-
ctx.save();
|
|
558
649
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
559
650
|
}
|
|
560
651
|
}
|
|
561
|
-
this
|
|
652
|
+
this.#print("Can not set pattern.");
|
|
562
653
|
return kei_lisp.Cons.nil;
|
|
563
654
|
} catch {
|
|
564
|
-
this
|
|
655
|
+
this.#print("Can not set pattern.");
|
|
565
656
|
return kei_lisp.Cons.nil;
|
|
566
657
|
}
|
|
567
|
-
this
|
|
658
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
568
659
|
return kei_lisp.Cons.nil;
|
|
569
660
|
}
|
|
570
|
-
gQuadCurveTo(
|
|
661
|
+
gQuadCurveTo(arguments_) {
|
|
571
662
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
572
663
|
if (this.isOpen) try {
|
|
573
|
-
if (
|
|
574
|
-
const a0 =
|
|
575
|
-
const cdr1 =
|
|
664
|
+
if (arguments_.length() === 4) {
|
|
665
|
+
const a0 = arguments_.car;
|
|
666
|
+
const cdr1 = arguments_.cdr;
|
|
576
667
|
const a1 = cdr1.car;
|
|
577
668
|
const cdr2 = cdr1.cdr;
|
|
578
669
|
const a2 = cdr2.car;
|
|
579
670
|
const a3 = cdr2.cdr.car;
|
|
580
671
|
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2) && kei_lisp.Cons.isNumber(a3)) {
|
|
581
672
|
this.ctx.quadraticCurveTo(a0, a1, a2, a3);
|
|
582
|
-
this.ctx.save();
|
|
583
673
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
584
674
|
}
|
|
585
675
|
}
|
|
586
|
-
this
|
|
676
|
+
this.#print("Can not draw quadratic curve.");
|
|
587
677
|
return kei_lisp.Cons.nil;
|
|
588
678
|
} catch {
|
|
589
|
-
this
|
|
679
|
+
this.#print("Can not draw quadratic curve.");
|
|
590
680
|
return kei_lisp.Cons.nil;
|
|
591
681
|
}
|
|
592
|
-
this
|
|
682
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
593
683
|
return kei_lisp.Cons.nil;
|
|
594
684
|
}
|
|
595
|
-
gSaveJpeg() {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
anImage.src = this.canvas.toDataURL("image/jpeg");
|
|
601
|
-
const link = document.createElement("a");
|
|
602
|
-
link.href = anImage.src;
|
|
603
|
-
link.download = "canvas";
|
|
604
|
-
document.body.append(link);
|
|
605
|
-
link.click();
|
|
606
|
-
link.remove();
|
|
607
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
608
|
-
} catch {
|
|
609
|
-
this._print("Can not save jpeg. If you are using an image in the canvas, you can't save jpeg.");
|
|
610
|
-
return kei_lisp.Cons.nil;
|
|
611
|
-
}
|
|
612
|
-
this._print("The canvas is closed and cannot be executed.");
|
|
613
|
-
return kei_lisp.Cons.nil;
|
|
685
|
+
gSaveJpeg(arguments_) {
|
|
686
|
+
return this.saveCanvas(arguments_, "image/jpeg", "jpeg");
|
|
687
|
+
}
|
|
688
|
+
gSavePng(arguments_) {
|
|
689
|
+
return this.saveCanvas(arguments_, "image/png", "png");
|
|
614
690
|
}
|
|
615
|
-
|
|
691
|
+
/**
|
|
692
|
+
* Shared implementation of `gsave-jpeg` / `gsave-png`. With no argument it
|
|
693
|
+
* triggers a browser download; with a single string argument it writes the
|
|
694
|
+
* encoded image to that file path on Node.js.
|
|
695
|
+
* @param arguments_ - the evaluated argument list (empty, or one path string)
|
|
696
|
+
* @param mimeType - the image MIME type to encode
|
|
697
|
+
* @param label - the format name used in diagnostics ("jpeg" / "png")
|
|
698
|
+
* @return `t` on success, `Cons.nil` otherwise
|
|
699
|
+
*/
|
|
700
|
+
saveCanvas(arguments_, mimeType, label) {
|
|
616
701
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
617
|
-
if (this.isOpen)
|
|
618
|
-
const
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
link.href = anImage.src;
|
|
623
|
-
link.download = "canvas";
|
|
624
|
-
document.body.append(link);
|
|
625
|
-
link.click();
|
|
626
|
-
link.remove();
|
|
627
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
628
|
-
} catch {
|
|
629
|
-
this._print("Can not save png. If you are using an image in the canvas, you can't save png.");
|
|
702
|
+
if (this.isOpen) {
|
|
703
|
+
const length_ = arguments_.length();
|
|
704
|
+
if (length_ === 0) return this.#downloadCanvas(mimeType, label);
|
|
705
|
+
if (length_ === 1 && kei_lisp.Cons.isString(arguments_.car)) return this.#writeCanvasToFile(arguments_.car, mimeType, label);
|
|
706
|
+
this.#print(`Can not save ${label}.`);
|
|
630
707
|
return kei_lisp.Cons.nil;
|
|
631
708
|
}
|
|
632
|
-
this
|
|
709
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
633
710
|
return kei_lisp.Cons.nil;
|
|
634
711
|
}
|
|
635
|
-
gScale(
|
|
712
|
+
gScale(arguments_) {
|
|
636
713
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
637
714
|
if (this.isOpen) try {
|
|
638
|
-
if (
|
|
639
|
-
const a0 =
|
|
640
|
-
const a1 =
|
|
715
|
+
if (arguments_.length() === 2) {
|
|
716
|
+
const a0 = arguments_.car;
|
|
717
|
+
const a1 = arguments_.cdr.car;
|
|
641
718
|
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1)) {
|
|
642
719
|
this.ctx.scale(a0, a1);
|
|
643
|
-
this.ctx.save();
|
|
644
720
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
645
721
|
}
|
|
646
722
|
}
|
|
647
|
-
this
|
|
723
|
+
this.#print("Can not scale.");
|
|
648
724
|
return kei_lisp.Cons.nil;
|
|
649
725
|
} catch {
|
|
650
|
-
this
|
|
726
|
+
this.#print("Can not scale.");
|
|
651
727
|
return kei_lisp.Cons.nil;
|
|
652
728
|
}
|
|
653
|
-
this
|
|
729
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
654
730
|
return kei_lisp.Cons.nil;
|
|
655
731
|
}
|
|
656
|
-
gShadowBlur(
|
|
732
|
+
gShadowBlur(arguments_) {
|
|
657
733
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
658
734
|
if (this.isOpen) {
|
|
659
|
-
if (
|
|
660
|
-
this.ctx.
|
|
661
|
-
this.ctx.save();
|
|
735
|
+
if (arguments_.length() === 1 && kei_lisp.Cons.isNumber(arguments_.car)) {
|
|
736
|
+
this.ctx.shadowBlur = arguments_.car;
|
|
662
737
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
663
738
|
}
|
|
664
|
-
this
|
|
739
|
+
this.#print("Can not set shadow blur.");
|
|
665
740
|
return kei_lisp.Cons.nil;
|
|
666
741
|
}
|
|
667
|
-
this
|
|
742
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
668
743
|
return kei_lisp.Cons.nil;
|
|
669
744
|
}
|
|
670
|
-
gShadowColor(
|
|
745
|
+
gShadowColor(arguments_) {
|
|
671
746
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
672
747
|
if (this.isOpen) try {
|
|
673
|
-
if (
|
|
674
|
-
const aColor = this.selectColor(
|
|
748
|
+
if (arguments_.length() === 1) {
|
|
749
|
+
const aColor = this.selectColor(arguments_);
|
|
675
750
|
this.ctx.shadowColor = aColor;
|
|
676
|
-
this.ctx.save();
|
|
677
751
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
678
752
|
}
|
|
679
|
-
this
|
|
753
|
+
this.#print("Can not set shadow color.");
|
|
680
754
|
return kei_lisp.Cons.nil;
|
|
681
755
|
} catch {
|
|
682
|
-
this
|
|
756
|
+
this.#print("Can not set shadow color.");
|
|
683
757
|
return kei_lisp.Cons.nil;
|
|
684
758
|
}
|
|
685
|
-
this
|
|
759
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
686
760
|
return kei_lisp.Cons.nil;
|
|
687
761
|
}
|
|
688
|
-
gShadowOffsetX(
|
|
762
|
+
gShadowOffsetX(arguments_) {
|
|
689
763
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
690
764
|
if (this.isOpen) {
|
|
691
|
-
if (
|
|
692
|
-
this.ctx.shadowOffsetX =
|
|
693
|
-
this.ctx.save();
|
|
765
|
+
if (arguments_.length() === 1 && kei_lisp.Cons.isNumber(arguments_.car)) {
|
|
766
|
+
this.ctx.shadowOffsetX = arguments_.car;
|
|
694
767
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
695
768
|
}
|
|
696
|
-
this
|
|
769
|
+
this.#print("Can not set shadow offsetX.");
|
|
697
770
|
return kei_lisp.Cons.nil;
|
|
698
771
|
}
|
|
699
|
-
this
|
|
772
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
700
773
|
return kei_lisp.Cons.nil;
|
|
701
774
|
}
|
|
702
|
-
gShadowOffsetY(
|
|
775
|
+
gShadowOffsetY(arguments_) {
|
|
703
776
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
704
777
|
if (this.isOpen) {
|
|
705
|
-
if (
|
|
706
|
-
this.ctx.shadowOffsetY =
|
|
707
|
-
this.ctx.save();
|
|
778
|
+
if (arguments_.length() === 1 && kei_lisp.Cons.isNumber(arguments_.car)) {
|
|
779
|
+
this.ctx.shadowOffsetY = arguments_.car;
|
|
708
780
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
709
781
|
}
|
|
710
|
-
this
|
|
782
|
+
this.#print("Can not set shadow offsetY.");
|
|
711
783
|
return kei_lisp.Cons.nil;
|
|
712
784
|
}
|
|
713
|
-
this
|
|
785
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
714
786
|
return kei_lisp.Cons.nil;
|
|
715
787
|
}
|
|
716
|
-
gSleep(
|
|
788
|
+
gSleep(arguments_) {
|
|
717
789
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
718
790
|
if (this.isOpen) {
|
|
719
791
|
const sleep = (ms) => {
|
|
720
792
|
const time = Date.now() + ms;
|
|
721
793
|
while (Date.now() < time);
|
|
722
794
|
};
|
|
723
|
-
if (
|
|
724
|
-
sleep(
|
|
795
|
+
if (arguments_.length() === 1 && kei_lisp.Cons.isNumber(arguments_.car)) {
|
|
796
|
+
sleep(arguments_.car);
|
|
725
797
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
726
798
|
}
|
|
727
|
-
this
|
|
799
|
+
this.#print("Can not sleep");
|
|
728
800
|
return kei_lisp.Cons.nil;
|
|
729
801
|
}
|
|
730
|
-
this
|
|
802
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
731
803
|
return kei_lisp.Cons.nil;
|
|
732
804
|
}
|
|
733
805
|
gStartPath() {
|
|
734
806
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
735
807
|
if (this.isOpen) try {
|
|
736
808
|
this.ctx.beginPath();
|
|
737
|
-
this.ctx.save();
|
|
738
809
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
739
810
|
} catch {
|
|
740
|
-
this
|
|
811
|
+
this.#print("Can not start path.");
|
|
741
812
|
return kei_lisp.Cons.nil;
|
|
742
813
|
}
|
|
743
|
-
this
|
|
814
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
744
815
|
return kei_lisp.Cons.nil;
|
|
745
816
|
}
|
|
746
817
|
gStroke() {
|
|
747
818
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
748
819
|
if (this.isOpen) try {
|
|
749
820
|
this.ctx.stroke();
|
|
750
|
-
this.ctx.save();
|
|
751
821
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
752
822
|
} catch {
|
|
753
|
-
this
|
|
823
|
+
this.#print("Can not stroke.");
|
|
754
824
|
return kei_lisp.Cons.nil;
|
|
755
825
|
}
|
|
756
|
-
this
|
|
826
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
757
827
|
return kei_lisp.Cons.nil;
|
|
758
828
|
}
|
|
759
|
-
gStrokeColor(
|
|
829
|
+
gStrokeColor(arguments_) {
|
|
760
830
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
761
831
|
if (this.isOpen) try {
|
|
762
|
-
if (
|
|
763
|
-
const aColor = this.selectColor(
|
|
832
|
+
if (arguments_.length() >= 1) {
|
|
833
|
+
const aColor = this.selectColor(arguments_);
|
|
764
834
|
this.ctx.strokeStyle = aColor;
|
|
765
|
-
this.ctx.save();
|
|
766
835
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
767
836
|
}
|
|
768
|
-
this
|
|
837
|
+
this.#print("Can not set stroke color");
|
|
769
838
|
return kei_lisp.Cons.nil;
|
|
770
839
|
} catch {
|
|
771
|
-
this
|
|
840
|
+
this.#print("Can not set stroke color");
|
|
772
841
|
return kei_lisp.Cons.nil;
|
|
773
842
|
}
|
|
774
|
-
this
|
|
843
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
775
844
|
return kei_lisp.Cons.nil;
|
|
776
845
|
}
|
|
777
|
-
gStrokeRect(
|
|
846
|
+
gStrokeRect(arguments_) {
|
|
778
847
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
779
848
|
if (this.isOpen) try {
|
|
780
|
-
if (
|
|
781
|
-
const a0 =
|
|
782
|
-
const cdr1 =
|
|
849
|
+
if (arguments_.length() === 4) {
|
|
850
|
+
const a0 = arguments_.car;
|
|
851
|
+
const cdr1 = arguments_.cdr;
|
|
783
852
|
const a1 = cdr1.car;
|
|
784
853
|
const cdr2 = cdr1.cdr;
|
|
785
854
|
const a2 = cdr2.car;
|
|
786
855
|
const a3 = cdr2.cdr.car;
|
|
787
856
|
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2) && kei_lisp.Cons.isNumber(a3)) {
|
|
788
857
|
this.ctx.strokeRect(a0, a1, a2, a3);
|
|
789
|
-
this.ctx.save();
|
|
790
858
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
791
859
|
}
|
|
792
860
|
}
|
|
793
|
-
this
|
|
861
|
+
this.#print("Can not draw stroke rectangle.");
|
|
794
862
|
return kei_lisp.Cons.nil;
|
|
795
863
|
} catch {
|
|
796
|
-
this
|
|
864
|
+
this.#print("Can not draw stroke rectangle.");
|
|
797
865
|
return kei_lisp.Cons.nil;
|
|
798
866
|
}
|
|
799
|
-
this
|
|
867
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
800
868
|
return kei_lisp.Cons.nil;
|
|
801
869
|
}
|
|
802
|
-
gStrokeText(
|
|
870
|
+
gStrokeText(arguments_) {
|
|
803
871
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
804
872
|
if (this.isOpen) try {
|
|
805
|
-
if (
|
|
806
|
-
const a0 =
|
|
807
|
-
const cdr1 =
|
|
873
|
+
if (arguments_.length() === 3) {
|
|
874
|
+
const a0 = arguments_.car;
|
|
875
|
+
const cdr1 = arguments_.cdr;
|
|
808
876
|
const a1 = cdr1.car;
|
|
809
877
|
const a2 = cdr1.cdr.car;
|
|
810
878
|
if (kei_lisp.Cons.isString(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2)) {
|
|
811
879
|
this.ctx.strokeText(a0, a1, a2);
|
|
812
|
-
this.ctx.save();
|
|
813
880
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
814
881
|
}
|
|
815
882
|
}
|
|
816
|
-
this
|
|
883
|
+
this.#print("Can not draw stroke text.");
|
|
817
884
|
return kei_lisp.Cons.nil;
|
|
818
885
|
} catch {
|
|
819
|
-
this
|
|
886
|
+
this.#print("Can not draw stroke text.");
|
|
820
887
|
return kei_lisp.Cons.nil;
|
|
821
888
|
}
|
|
822
|
-
this
|
|
889
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
823
890
|
return kei_lisp.Cons.nil;
|
|
824
891
|
}
|
|
825
|
-
gStrokeTri(
|
|
892
|
+
gStrokeTri(arguments_) {
|
|
826
893
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
827
894
|
if (this.isOpen) try {
|
|
828
|
-
if (
|
|
829
|
-
const a0 =
|
|
830
|
-
const cdr1 =
|
|
895
|
+
if (arguments_.length() === 6) {
|
|
896
|
+
const a0 = arguments_.car;
|
|
897
|
+
const cdr1 = arguments_.cdr;
|
|
831
898
|
const a1 = cdr1.car;
|
|
832
899
|
const cdr2 = cdr1.cdr;
|
|
833
900
|
const a2 = cdr2.car;
|
|
@@ -843,231 +910,208 @@ var GraphicsPlugin = class GraphicsPlugin extends Object {
|
|
|
843
910
|
this.ctx.lineTo(a4, a5);
|
|
844
911
|
this.ctx.closePath();
|
|
845
912
|
this.ctx.stroke();
|
|
846
|
-
this.ctx.save();
|
|
847
913
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
848
914
|
}
|
|
849
915
|
}
|
|
850
|
-
this
|
|
916
|
+
this.#print("Can not draw stroke triangle.");
|
|
851
917
|
return kei_lisp.Cons.nil;
|
|
852
918
|
} catch {
|
|
853
|
-
this
|
|
919
|
+
this.#print("Can not draw stroke triangle.");
|
|
854
920
|
return kei_lisp.Cons.nil;
|
|
855
921
|
}
|
|
856
|
-
this
|
|
922
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
857
923
|
return kei_lisp.Cons.nil;
|
|
858
924
|
}
|
|
859
|
-
gTextAlign(
|
|
925
|
+
gTextAlign(arguments_) {
|
|
860
926
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
861
927
|
if (this.isOpen) try {
|
|
862
|
-
if (
|
|
863
|
-
this.ctx.textAlign =
|
|
864
|
-
this.ctx.save();
|
|
928
|
+
if (arguments_.length() === 1 && kei_lisp.Cons.isString(arguments_.car)) {
|
|
929
|
+
this.ctx.textAlign = arguments_.car;
|
|
865
930
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
866
931
|
}
|
|
867
|
-
this
|
|
932
|
+
this.#print("Can not set text align.");
|
|
868
933
|
return kei_lisp.Cons.nil;
|
|
869
934
|
} catch {
|
|
870
|
-
this
|
|
935
|
+
this.#print("Can not set text align.");
|
|
871
936
|
return kei_lisp.Cons.nil;
|
|
872
937
|
}
|
|
873
|
-
this
|
|
938
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
874
939
|
return kei_lisp.Cons.nil;
|
|
875
940
|
}
|
|
876
|
-
gTextBaseline(
|
|
941
|
+
gTextBaseline(arguments_) {
|
|
877
942
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
878
943
|
if (this.isOpen) try {
|
|
879
|
-
if (
|
|
880
|
-
this.ctx.textBaseline =
|
|
881
|
-
this.ctx.save();
|
|
944
|
+
if (arguments_.length() === 1 && kei_lisp.Cons.isString(arguments_.car)) {
|
|
945
|
+
this.ctx.textBaseline = arguments_.car;
|
|
882
946
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
883
947
|
}
|
|
884
|
-
this
|
|
948
|
+
this.#print("Can not set text baseline.");
|
|
885
949
|
return kei_lisp.Cons.nil;
|
|
886
950
|
} catch {
|
|
887
|
-
this
|
|
951
|
+
this.#print("Can not set text baseline.");
|
|
888
952
|
return kei_lisp.Cons.nil;
|
|
889
953
|
}
|
|
890
|
-
this
|
|
954
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
891
955
|
return kei_lisp.Cons.nil;
|
|
892
956
|
}
|
|
893
|
-
gTextDirection(
|
|
957
|
+
gTextDirection(arguments_) {
|
|
894
958
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
895
959
|
if (this.isOpen) try {
|
|
896
|
-
if (
|
|
897
|
-
|
|
898
|
-
this.ctx.direction = aString;
|
|
899
|
-
this.ctx.save();
|
|
960
|
+
if (arguments_.length() === 1 && kei_lisp.Cons.isString(arguments_.car)) {
|
|
961
|
+
this.ctx.direction = arguments_.car;
|
|
900
962
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
901
963
|
}
|
|
902
|
-
this
|
|
964
|
+
this.#print("Can not set text direction.");
|
|
903
965
|
return kei_lisp.Cons.nil;
|
|
904
966
|
} catch {
|
|
905
|
-
this
|
|
967
|
+
this.#print("Can not set text direction.");
|
|
906
968
|
return kei_lisp.Cons.nil;
|
|
907
969
|
}
|
|
908
|
-
this
|
|
970
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
909
971
|
return kei_lisp.Cons.nil;
|
|
910
972
|
}
|
|
911
|
-
gTextFont(
|
|
973
|
+
gTextFont(arguments_) {
|
|
912
974
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
913
975
|
if (this.isOpen) try {
|
|
914
|
-
if (
|
|
915
|
-
this.ctx.font =
|
|
916
|
-
this.ctx.save();
|
|
976
|
+
if (arguments_.length() === 1 && kei_lisp.Cons.isString(arguments_.car)) {
|
|
977
|
+
this.ctx.font = arguments_.car;
|
|
917
978
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
918
979
|
}
|
|
919
|
-
this
|
|
980
|
+
this.#print("Can not set text font.");
|
|
920
981
|
return kei_lisp.Cons.nil;
|
|
921
982
|
} catch {
|
|
922
|
-
this
|
|
983
|
+
this.#print("Can not set text font.");
|
|
923
984
|
return kei_lisp.Cons.nil;
|
|
924
985
|
}
|
|
925
|
-
this
|
|
986
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
926
987
|
return kei_lisp.Cons.nil;
|
|
927
988
|
}
|
|
928
|
-
gTranslate(
|
|
989
|
+
gTranslate(arguments_) {
|
|
929
990
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
930
991
|
if (this.isOpen) try {
|
|
931
|
-
if (
|
|
932
|
-
const a0 =
|
|
933
|
-
const a1 =
|
|
992
|
+
if (arguments_.length() === 2) {
|
|
993
|
+
const a0 = arguments_.car;
|
|
994
|
+
const a1 = arguments_.cdr.car;
|
|
934
995
|
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1)) {
|
|
935
996
|
this.ctx.translate(a0, a1);
|
|
936
|
-
this.ctx.save();
|
|
937
997
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
938
998
|
}
|
|
939
999
|
}
|
|
940
|
-
this
|
|
1000
|
+
this.#print("Can not translate.");
|
|
941
1001
|
return kei_lisp.Cons.nil;
|
|
942
1002
|
} catch {
|
|
943
|
-
this
|
|
1003
|
+
this.#print("Can not translate.");
|
|
944
1004
|
return kei_lisp.Cons.nil;
|
|
945
1005
|
}
|
|
946
|
-
this
|
|
1006
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
947
1007
|
return kei_lisp.Cons.nil;
|
|
948
1008
|
}
|
|
949
|
-
gRect(
|
|
1009
|
+
gRect(arguments_) {
|
|
950
1010
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
951
1011
|
if (this.isOpen) try {
|
|
952
|
-
if (
|
|
953
|
-
const a0 =
|
|
954
|
-
const cdr1 =
|
|
1012
|
+
if (arguments_.length() === 4) {
|
|
1013
|
+
const a0 = arguments_.car;
|
|
1014
|
+
const cdr1 = arguments_.cdr;
|
|
955
1015
|
const a1 = cdr1.car;
|
|
956
1016
|
const cdr2 = cdr1.cdr;
|
|
957
1017
|
const a2 = cdr2.car;
|
|
958
1018
|
const a3 = cdr2.cdr.car;
|
|
959
1019
|
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2) && kei_lisp.Cons.isNumber(a3)) {
|
|
960
1020
|
this.ctx.rect(a0, a1, a2, a3);
|
|
961
|
-
this.ctx.save();
|
|
962
1021
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
963
1022
|
}
|
|
964
1023
|
}
|
|
965
|
-
this
|
|
1024
|
+
this.#print("Can not draw rectangle.");
|
|
966
1025
|
return kei_lisp.Cons.nil;
|
|
967
1026
|
} catch {
|
|
968
|
-
this
|
|
1027
|
+
this.#print("Can not draw rectangle.");
|
|
969
1028
|
return kei_lisp.Cons.nil;
|
|
970
1029
|
}
|
|
971
|
-
this
|
|
1030
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
972
1031
|
return kei_lisp.Cons.nil;
|
|
973
1032
|
}
|
|
974
|
-
gRotate(
|
|
1033
|
+
gRotate(arguments_) {
|
|
975
1034
|
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
976
1035
|
if (this.isOpen) try {
|
|
977
|
-
if (
|
|
978
|
-
this.ctx.rotate(Math.PI / 180 *
|
|
979
|
-
this.ctx.save();
|
|
1036
|
+
if (arguments_.length() === 1 && kei_lisp.Cons.isNumber(arguments_.car)) {
|
|
1037
|
+
this.ctx.rotate(Math.PI / 180 * arguments_.car);
|
|
980
1038
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
981
1039
|
}
|
|
982
|
-
this
|
|
1040
|
+
this.#print("Can not rotate.");
|
|
983
1041
|
return kei_lisp.Cons.nil;
|
|
984
1042
|
} catch {
|
|
985
|
-
this
|
|
1043
|
+
this.#print("Can not rotate.");
|
|
986
1044
|
return kei_lisp.Cons.nil;
|
|
987
1045
|
}
|
|
988
|
-
this
|
|
1046
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
1047
|
+
return kei_lisp.Cons.nil;
|
|
1048
|
+
}
|
|
1049
|
+
/**
|
|
1050
|
+
* Pushes the current drawing state (styles, transform, clip) onto the
|
|
1051
|
+
* context's state stack. Pairs with `gRestore` to let Lisp callers manage
|
|
1052
|
+
* state explicitly. Replaces the legacy per-method `ctx.save()` calls, which
|
|
1053
|
+
* pushed state on every draw with no matching `restore()` and grew the stack
|
|
1054
|
+
* unbounded.
|
|
1055
|
+
* @return `t` on success, `Cons.nil` otherwise
|
|
1056
|
+
*/
|
|
1057
|
+
gSave() {
|
|
1058
|
+
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
1059
|
+
if (this.isOpen) try {
|
|
1060
|
+
this.ctx.save();
|
|
1061
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
1062
|
+
} catch {
|
|
1063
|
+
this.#print("Can not save.");
|
|
1064
|
+
return kei_lisp.Cons.nil;
|
|
1065
|
+
}
|
|
1066
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
1067
|
+
return kei_lisp.Cons.nil;
|
|
1068
|
+
}
|
|
1069
|
+
/**
|
|
1070
|
+
* Pops the most recently saved drawing state off the context's state stack.
|
|
1071
|
+
* Pairs with `gSave`. Popping an empty stack is a no-op per the Canvas spec.
|
|
1072
|
+
* @return `t` on success, `Cons.nil` otherwise
|
|
1073
|
+
*/
|
|
1074
|
+
gRestore() {
|
|
1075
|
+
if (!this.checkSupport()) return kei_lisp.Cons.nil;
|
|
1076
|
+
if (this.isOpen) try {
|
|
1077
|
+
this.ctx.restore();
|
|
1078
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
1079
|
+
} catch {
|
|
1080
|
+
this.#print("Can not restore.");
|
|
1081
|
+
return kei_lisp.Cons.nil;
|
|
1082
|
+
}
|
|
1083
|
+
this.#print("The canvas is closed and cannot be executed.");
|
|
989
1084
|
return kei_lisp.Cons.nil;
|
|
990
1085
|
}
|
|
991
1086
|
/**
|
|
992
1087
|
* Parses a color spec from the head of the argument Cons. Accepts
|
|
993
1088
|
* (1 string), (3 numbers — rgb), or (4 numbers — rgba); falls back to
|
|
994
1089
|
* `'black'` on anything else (legacy behavior).
|
|
995
|
-
* @param
|
|
1090
|
+
* @param arguments_ - the argument Cons to parse
|
|
996
1091
|
* @return CSS color string
|
|
997
1092
|
*/
|
|
998
|
-
selectColor(
|
|
1093
|
+
selectColor(arguments_) {
|
|
999
1094
|
let aColor = "black";
|
|
1000
|
-
const
|
|
1001
|
-
const a0 =
|
|
1002
|
-
if (
|
|
1003
|
-
else if (
|
|
1004
|
-
const cdr1 =
|
|
1095
|
+
const length_ = arguments_.length();
|
|
1096
|
+
const a0 = arguments_.car;
|
|
1097
|
+
if (length_ === 1 && kei_lisp.Cons.isString(a0)) aColor = a0;
|
|
1098
|
+
else if (length_ === 3) {
|
|
1099
|
+
const cdr1 = arguments_.cdr;
|
|
1005
1100
|
const a1 = cdr1.car;
|
|
1006
1101
|
const a2 = cdr1.cdr.car;
|
|
1007
1102
|
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2)) aColor = `rgb(${a0}, ${a1}, ${a2})`;
|
|
1008
|
-
else this
|
|
1009
|
-
} else if (
|
|
1010
|
-
const cdr1 =
|
|
1103
|
+
else this.#print("Can not set color. set color \"black\".");
|
|
1104
|
+
} else if (length_ === 4) {
|
|
1105
|
+
const cdr1 = arguments_.cdr;
|
|
1011
1106
|
const a1 = cdr1.car;
|
|
1012
1107
|
const cdr2 = cdr1.cdr;
|
|
1013
1108
|
const a2 = cdr2.car;
|
|
1014
1109
|
const a3 = cdr2.cdr.car;
|
|
1015
1110
|
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2) && kei_lisp.Cons.isNumber(a3)) aColor = `rgba(${a0}, ${a1}, ${a2}, ${a3})`;
|
|
1016
|
-
else this
|
|
1017
|
-
} else this
|
|
1111
|
+
else this.#print("Can not set color. set color \"black\".");
|
|
1112
|
+
} else this.#print("Can not set color. set color \"black\".");
|
|
1018
1113
|
return aColor;
|
|
1019
1114
|
}
|
|
1020
|
-
/**
|
|
1021
|
-
* Builds the dispatch table.
|
|
1022
|
-
* @return the dispatch table
|
|
1023
|
-
*/
|
|
1024
|
-
static setup() {
|
|
1025
|
-
const aTable = /* @__PURE__ */ new Map();
|
|
1026
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("galpha"), "gAlpha");
|
|
1027
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("garc"), "gArc");
|
|
1028
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("garc-to"), "gArcTo");
|
|
1029
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gbezcurve-to"), "gBezCurveTo");
|
|
1030
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gclear"), "gClear");
|
|
1031
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gclose"), "gClose");
|
|
1032
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gcolor"), "gColor");
|
|
1033
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gfill"), "gFill");
|
|
1034
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gfill-color"), "gFillColor");
|
|
1035
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gfill-rect"), "gFillRect");
|
|
1036
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gfill-text"), "gFillText");
|
|
1037
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gfill-tri"), "gFillTri");
|
|
1038
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gfinish-path"), "gFinishPath");
|
|
1039
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gimage"), "gImage");
|
|
1040
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gmove-to"), "gMoveTo");
|
|
1041
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gline-to"), "gLineTo");
|
|
1042
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gline-cap"), "gLineCap");
|
|
1043
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gline-join"), "gLineJoin");
|
|
1044
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gline-width"), "gLineWidth");
|
|
1045
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gopen"), "gOpen");
|
|
1046
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gpattern"), "gPattern");
|
|
1047
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gquadcurve-to"), "gQuadCurveTo");
|
|
1048
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gsave-jpeg"), "gSaveJpeg");
|
|
1049
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gsave-png"), "gSavePng");
|
|
1050
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gscale"), "gScale");
|
|
1051
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gshadow-blur"), "gShadowBlur");
|
|
1052
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gshadow-color"), "gShadowColor");
|
|
1053
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gshadow-offsetx"), "gShadowOffsetX");
|
|
1054
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gshadow-offsety"), "gShadowOffsetY");
|
|
1055
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gsleep"), "gSleep");
|
|
1056
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gstart-path"), "gStartPath");
|
|
1057
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gstroke"), "gStroke");
|
|
1058
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gstroke-color"), "gStrokeColor");
|
|
1059
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gstroke-rect"), "gStrokeRect");
|
|
1060
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gstroke-text"), "gStrokeText");
|
|
1061
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gstroke-tri"), "gStrokeTri");
|
|
1062
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gtext-align"), "gTextAlign");
|
|
1063
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gtext-dire"), "gTextDirection");
|
|
1064
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gtext-font"), "gTextFont");
|
|
1065
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gtext-line"), "gTextBaseline");
|
|
1066
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gtranslate"), "gTranslate");
|
|
1067
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("grect"), "gRect");
|
|
1068
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("grotate"), "gRotate");
|
|
1069
|
-
return aTable;
|
|
1070
|
-
}
|
|
1071
1115
|
};
|
|
1072
1116
|
//#endregion
|
|
1073
1117
|
//#region src/index.ts
|