kei-lisp-plugin-graphics 3.0.1 → 4.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 +31 -13
- package/dist/index.cjs +303 -640
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -28
- package/dist/index.d.ts +28 -28
- package/dist/index.js +304 -641
- package/dist/index.js.map +1 -1
- package/lisp/animation.lisp +17 -0
- package/lisp/grid.lisp +26 -0
- package/lisp/palette.lisp +28 -0
- package/package.json +11 -10
package/dist/index.cjs
CHANGED
|
@@ -100,8 +100,15 @@ const COMPOSITE_OPERATIONS = /* @__PURE__ */ new Set([
|
|
|
100
100
|
* @class
|
|
101
101
|
* @classdesc Canvas2D drawing plugin for the kei-lisp interpreter. Implements
|
|
102
102
|
* the `KeiLispPlugin` contract (`name` / `has` / `apply`) and
|
|
103
|
-
* exposes 75 `g…` Lisp functions
|
|
104
|
-
*
|
|
103
|
+
* exposes 75 `g…` Lisp functions that proxy to a 2D rendering
|
|
104
|
+
* context. Failures (wrong arity,
|
|
105
|
+
* type mismatch, closed canvas, canvas-level errors) signal an
|
|
106
|
+
* `EvalError` that Lisp callers can intercept with
|
|
107
|
+
* `(handler-case … (eval-error (e) …))`. Two exceptions still go
|
|
108
|
+
* to `process.stderr` as diagnostics: asynchronous work (image
|
|
109
|
+
* loading, OffscreenCanvas file writes), which fails after the
|
|
110
|
+
* call has returned, and `selectColor`'s best-effort color
|
|
111
|
+
* parsing, which falls back to black instead of failing.
|
|
105
112
|
* @author Keisuke Ikeda
|
|
106
113
|
*/
|
|
107
114
|
var GraphicsPlugin = class GraphicsPlugin {
|
|
@@ -164,8 +171,6 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
164
171
|
aTable.set(kei_lisp.InterpretedSymbol.of("gtext-direction"), "gTextDirection");
|
|
165
172
|
aTable.set(kei_lisp.InterpretedSymbol.of("gtext-font"), "gTextFont");
|
|
166
173
|
aTable.set(kei_lisp.InterpretedSymbol.of("gtext-baseline"), "gTextBaseline");
|
|
167
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gtext-dire"), "gTextDirection");
|
|
168
|
-
aTable.set(kei_lisp.InterpretedSymbol.of("gtext-line"), "gTextBaseline");
|
|
169
174
|
aTable.set(kei_lisp.InterpretedSymbol.of("gtranslate"), "gTranslate");
|
|
170
175
|
aTable.set(kei_lisp.InterpretedSymbol.of("grect"), "gRect");
|
|
171
176
|
aTable.set(kei_lisp.InterpretedSymbol.of("grotate"), "gRotate");
|
|
@@ -229,11 +234,13 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
229
234
|
/**
|
|
230
235
|
* Writes a diagnostic line to `process.stderr`, matching the convention
|
|
231
236
|
* used by kei-lisp itself (`Applier.format` writes to `process.stdout`).
|
|
232
|
-
*
|
|
233
|
-
* (
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
+
* Used only where an `EvalError` cannot reach the caller: asynchronous
|
|
238
|
+
* work (image loading), best-effort color parsing, and the informational
|
|
239
|
+
* line printed by `gopen`. In a Node runtime this hits the real stderr; in
|
|
240
|
+
* a browser kei-lisp host (e.g. kei-lisp-web) the host typically swaps
|
|
241
|
+
* `process.stderr.write` for a sink that routes to the REPL output panel.
|
|
242
|
+
* In a plain browser with no `process` shim at all, the line falls back to
|
|
243
|
+
* `console.error` instead of throwing.
|
|
237
244
|
* @param line - the line to write
|
|
238
245
|
*/
|
|
239
246
|
#print(line) {
|
|
@@ -247,7 +254,9 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
247
254
|
/**
|
|
248
255
|
* Resolves an image for the given source and runs `draw` with it —
|
|
249
256
|
* synchronously when the image is already loaded, on its `load` event
|
|
250
|
-
* otherwise. A load failure prints a diagnostic once
|
|
257
|
+
* otherwise. A load failure prints a diagnostic once (the failure happens
|
|
258
|
+
* asynchronously, after the calling `g…` function has already returned, so
|
|
259
|
+
* it cannot signal an `EvalError`).
|
|
251
260
|
* @param source - the image URL / data URI
|
|
252
261
|
* @param draw - the drawing action to run once the image is available
|
|
253
262
|
*/
|
|
@@ -270,26 +279,37 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
270
279
|
});
|
|
271
280
|
}
|
|
272
281
|
/**
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
|
|
282
|
+
* Returns the 2D context, signaling an `EvalError` when the canvas exposes
|
|
283
|
+
* no usable context or has not been opened with `gopen`.
|
|
284
|
+
* @return the 2D rendering context
|
|
285
|
+
*/
|
|
286
|
+
#requireOpenContext() {
|
|
287
|
+
if (this.ctx === null) throw new kei_lisp.EvalError("Unable to initialize canvas. The browser or machine may not support it.");
|
|
288
|
+
if (!this.isOpen) throw new kei_lisp.EvalError("The canvas is closed and cannot be executed.");
|
|
289
|
+
return this.ctx;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Shared guard-and-dispatch skeleton for the `g…` methods: requires an
|
|
293
|
+
* open canvas context, runs `body`, and signals an `EvalError` carrying
|
|
294
|
+
* `failureMessage` when `body` returns `null` (bad arguments) or throws a
|
|
295
|
+
* canvas-level error. The error propagates through the evaluator, where
|
|
296
|
+
* Lisp callers can intercept it with
|
|
297
|
+
* `(handler-case … (eval-error (e) …))`.
|
|
298
|
+
* @param failureMessage - the message of the signaled `EvalError`
|
|
277
299
|
* @param body - the drawing action; returns the Lisp result, or `null` on
|
|
278
300
|
* bad arguments
|
|
279
|
-
* @return the body's result
|
|
301
|
+
* @return the body's result
|
|
280
302
|
*/
|
|
281
303
|
#execute(failureMessage, body) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
285
|
-
return kei_lisp.Cons.nil;
|
|
286
|
-
}
|
|
304
|
+
const context = this.#requireOpenContext();
|
|
305
|
+
let result;
|
|
287
306
|
try {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
307
|
+
result = body(context);
|
|
308
|
+
} catch (error) {
|
|
309
|
+
throw error instanceof kei_lisp.EvalError ? error : new kei_lisp.EvalError(failureMessage);
|
|
310
|
+
}
|
|
311
|
+
if (result === null) throw new kei_lisp.EvalError(failureMessage);
|
|
312
|
+
return result;
|
|
293
313
|
}
|
|
294
314
|
/**
|
|
295
315
|
* Reads a single string argument and validates it against an allowlist.
|
|
@@ -303,7 +323,9 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
303
323
|
return allowed.has(arguments_.car) ? arguments_.car : null;
|
|
304
324
|
}
|
|
305
325
|
/**
|
|
306
|
-
* Reads exactly `count` numbers from the argument list.
|
|
326
|
+
* Reads exactly `count` numbers from the argument list. kei-lisp v3
|
|
327
|
+
* evaluates integers to `bigint` and exact division to `Rational`, so each
|
|
328
|
+
* value is converted to a JS float for the Canvas 2D API.
|
|
307
329
|
* @param arguments_ - the evaluated argument list
|
|
308
330
|
* @param count - the expected argument count
|
|
309
331
|
* @return the numbers, or `null` on wrong arity or a non-number argument
|
|
@@ -314,7 +336,7 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
314
336
|
let rest = arguments_;
|
|
315
337
|
for (let index = 0; index < count; index++) {
|
|
316
338
|
if (!kei_lisp.Cons.isNumber(rest.car)) return null;
|
|
317
|
-
values.push(rest.car);
|
|
339
|
+
values.push(kei_lisp.Numeric.toFloat(rest.car));
|
|
318
340
|
rest = rest.cdr;
|
|
319
341
|
}
|
|
320
342
|
return values;
|
|
@@ -359,7 +381,7 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
359
381
|
const offset = stops[index];
|
|
360
382
|
const color = stops[index + 1];
|
|
361
383
|
if (!kei_lisp.Cons.isNumber(offset) || !kei_lisp.Cons.isString(color)) return false;
|
|
362
|
-
gradient.addColorStop(offset, color);
|
|
384
|
+
gradient.addColorStop(kei_lisp.Numeric.toFloat(offset), color);
|
|
363
385
|
}
|
|
364
386
|
return true;
|
|
365
387
|
}
|
|
@@ -384,13 +406,10 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
384
406
|
* no `document` — those callers must pass a file path instead.
|
|
385
407
|
* @param mimeType - the image MIME type to encode
|
|
386
408
|
* @param label - the format name used in diagnostics ("jpeg" / "png")
|
|
387
|
-
* @return `t` on success
|
|
409
|
+
* @return `t` on success
|
|
388
410
|
*/
|
|
389
411
|
#downloadCanvas(mimeType, label) {
|
|
390
|
-
if (typeof document === "undefined" || !("toDataURL" in this.canvas)) {
|
|
391
|
-
this.#print(`Can not save ${label}. Browser download needs a DOM and an HTMLCanvasElement; pass a file path to save on Node.js.`);
|
|
392
|
-
return kei_lisp.Cons.nil;
|
|
393
|
-
}
|
|
412
|
+
if (typeof document === "undefined" || !("toDataURL" in this.canvas)) throw new kei_lisp.EvalError(`Can not save ${label}. Browser download needs a DOM and an HTMLCanvasElement; pass a file path to save on Node.js.`);
|
|
394
413
|
try {
|
|
395
414
|
const link = document.createElement("a");
|
|
396
415
|
link.href = this.canvas.toDataURL(mimeType);
|
|
@@ -400,8 +419,7 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
400
419
|
link.remove();
|
|
401
420
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
402
421
|
} catch {
|
|
403
|
-
|
|
404
|
-
return kei_lisp.Cons.nil;
|
|
422
|
+
throw new kei_lisp.EvalError(`Can not save ${label}. If you are using an image in the canvas, you can't save ${label}.`);
|
|
405
423
|
}
|
|
406
424
|
}
|
|
407
425
|
/**
|
|
@@ -414,14 +432,12 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
414
432
|
* @param path - the destination file path
|
|
415
433
|
* @param mimeType - the image MIME type to encode
|
|
416
434
|
* @param label - the format name used in diagnostics ("jpeg" / "png")
|
|
417
|
-
* @return `t` on success
|
|
435
|
+
* @return `t` on success
|
|
418
436
|
*/
|
|
419
437
|
#writeCanvasToFile(path, mimeType, label) {
|
|
420
|
-
const
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
return kei_lisp.Cons.nil;
|
|
424
|
-
}
|
|
438
|
+
const getBuiltinModule = globalThis.process?.getBuiltinModule;
|
|
439
|
+
const fs = typeof getBuiltinModule === "function" ? getBuiltinModule("node:fs") : void 0;
|
|
440
|
+
if (fs === void 0) throw new kei_lisp.EvalError(`Can not save ${label}. Saving to a file path requires Node.js.`);
|
|
425
441
|
try {
|
|
426
442
|
if ("toDataURL" in this.canvas) {
|
|
427
443
|
const dataUrl = this.canvas.toDataURL(mimeType);
|
|
@@ -431,11 +447,12 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
431
447
|
}
|
|
432
448
|
this.canvas.convertToBlob({ type: mimeType }).then(async (blob) => {
|
|
433
449
|
fs.writeFileSync(path, new Uint8Array(await blob.arrayBuffer()));
|
|
450
|
+
}).catch(() => {
|
|
451
|
+
this.#print(`Can not save ${label}.`);
|
|
434
452
|
});
|
|
435
453
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
436
454
|
} catch {
|
|
437
|
-
|
|
438
|
-
return kei_lisp.Cons.nil;
|
|
455
|
+
throw new kei_lisp.EvalError(`Can not save ${label}.`);
|
|
439
456
|
}
|
|
440
457
|
}
|
|
441
458
|
/**
|
|
@@ -451,127 +468,45 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
451
468
|
* @param aSymbol - the call symbol
|
|
452
469
|
* @param arguments_ - the evaluated argument list
|
|
453
470
|
* @param _context - the interpreter context (unused by this plugin)
|
|
454
|
-
* @return the method's result
|
|
471
|
+
* @return the method's result
|
|
455
472
|
*/
|
|
456
473
|
apply(aSymbol, arguments_, _context) {
|
|
457
474
|
const methodName = GraphicsPlugin.#builtInFunctions.get(aSymbol);
|
|
458
|
-
if (methodName === void 0) {
|
|
459
|
-
this.#print(`I could find no procedure description for ${String(aSymbol)}`);
|
|
460
|
-
return kei_lisp.Cons.nil;
|
|
461
|
-
}
|
|
475
|
+
if (methodName === void 0) throw new kei_lisp.EvalError(`I could find no procedure description for ${String(aSymbol)}`);
|
|
462
476
|
return this[methodName].call(this, arguments_);
|
|
463
477
|
}
|
|
464
|
-
/**
|
|
465
|
-
* Checks whether the canvas exposes a usable 2D context, and narrows
|
|
466
|
-
* `this.ctx` to non-null for the caller when it returns true.
|
|
467
|
-
* @return type predicate — true when context is non-null
|
|
468
|
-
*/
|
|
469
|
-
checkSupport() {
|
|
470
|
-
if (this.ctx === null) {
|
|
471
|
-
this.#print("Unable to initialize canvas. The browser or machine may not support it.");
|
|
472
|
-
return false;
|
|
473
|
-
}
|
|
474
|
-
return true;
|
|
475
|
-
}
|
|
476
478
|
gAlpha(arguments_) {
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
if (
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
}
|
|
484
|
-
this.#print("Can not set alpha.");
|
|
485
|
-
return kei_lisp.Cons.nil;
|
|
486
|
-
} catch {
|
|
487
|
-
this.#print("Can not set alpha.");
|
|
488
|
-
return kei_lisp.Cons.nil;
|
|
489
|
-
}
|
|
490
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
491
|
-
return kei_lisp.Cons.nil;
|
|
479
|
+
return this.#execute("Can not set alpha.", (context) => {
|
|
480
|
+
const a = this.#numbers(arguments_, 1);
|
|
481
|
+
if (a === null) return null;
|
|
482
|
+
context.globalAlpha = a[0] <= 0 ? 0 : a[0] >= 1 ? 1 : a[0];
|
|
483
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
484
|
+
});
|
|
492
485
|
}
|
|
493
486
|
gArc(arguments_) {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
if (
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
const a2 = cdr2.car;
|
|
502
|
-
const cdr3 = cdr2.cdr;
|
|
503
|
-
const a3 = cdr3.car;
|
|
504
|
-
const cdr4 = cdr3.cdr;
|
|
505
|
-
const a4 = cdr4.car;
|
|
506
|
-
const a5 = cdr4.cdr.car;
|
|
507
|
-
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)) {
|
|
508
|
-
const isAFlag = a5 >= 0;
|
|
509
|
-
this.ctx.arc(a0, a1, a2, Math.PI / 180 * a3, Math.PI / 180 * a4, isAFlag);
|
|
510
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
this.#print("Can not draw arc.");
|
|
514
|
-
return kei_lisp.Cons.nil;
|
|
515
|
-
} catch {
|
|
516
|
-
this.#print("Can not draw arc.");
|
|
517
|
-
return kei_lisp.Cons.nil;
|
|
518
|
-
}
|
|
519
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
520
|
-
return kei_lisp.Cons.nil;
|
|
487
|
+
return this.#execute("Can not draw arc.", (context) => {
|
|
488
|
+
const a = this.#numbers(arguments_, 6);
|
|
489
|
+
if (a === null) return null;
|
|
490
|
+
const isAFlag = a[5] >= 0;
|
|
491
|
+
context.arc(a[0], a[1], a[2], Math.PI / 180 * a[3], Math.PI / 180 * a[4], isAFlag);
|
|
492
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
493
|
+
});
|
|
521
494
|
}
|
|
522
495
|
gArcTo(arguments_) {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
if (
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
const cdr2 = cdr1.cdr;
|
|
530
|
-
const a2 = cdr2.car;
|
|
531
|
-
const cdr3 = cdr2.cdr;
|
|
532
|
-
const a3 = cdr3.car;
|
|
533
|
-
const a4 = cdr3.cdr.car;
|
|
534
|
-
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)) {
|
|
535
|
-
this.ctx.arcTo(a0, a1, a2, a3, a4);
|
|
536
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
this.#print("Can not draw arc to.");
|
|
540
|
-
return kei_lisp.Cons.nil;
|
|
541
|
-
} catch {
|
|
542
|
-
this.#print("Can not draw arc to.");
|
|
543
|
-
return kei_lisp.Cons.nil;
|
|
544
|
-
}
|
|
545
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
546
|
-
return kei_lisp.Cons.nil;
|
|
496
|
+
return this.#execute("Can not draw arc to.", (context) => {
|
|
497
|
+
const a = this.#numbers(arguments_, 5);
|
|
498
|
+
if (a === null) return null;
|
|
499
|
+
context.arcTo(a[0], a[1], a[2], a[3], a[4]);
|
|
500
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
501
|
+
});
|
|
547
502
|
}
|
|
548
503
|
gBezCurveTo(arguments_) {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
if (
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
const cdr2 = cdr1.cdr;
|
|
556
|
-
const a2 = cdr2.car;
|
|
557
|
-
const cdr3 = cdr2.cdr;
|
|
558
|
-
const a3 = cdr3.car;
|
|
559
|
-
const cdr4 = cdr3.cdr;
|
|
560
|
-
const a4 = cdr4.car;
|
|
561
|
-
const a5 = cdr4.cdr.car;
|
|
562
|
-
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)) {
|
|
563
|
-
this.ctx.bezierCurveTo(a0, a1, a2, a3, a4, a5);
|
|
564
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
this.#print("Can not draw bezier curve.");
|
|
568
|
-
return kei_lisp.Cons.nil;
|
|
569
|
-
} catch {
|
|
570
|
-
this.#print("Can not draw bezier curve.");
|
|
571
|
-
return kei_lisp.Cons.nil;
|
|
572
|
-
}
|
|
573
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
574
|
-
return kei_lisp.Cons.nil;
|
|
504
|
+
return this.#execute("Can not draw bezier curve.", (context) => {
|
|
505
|
+
const a = this.#numbers(arguments_, 6);
|
|
506
|
+
if (a === null) return null;
|
|
507
|
+
context.bezierCurveTo(a[0], a[1], a[2], a[3], a[4], a[5]);
|
|
508
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
509
|
+
});
|
|
575
510
|
}
|
|
576
511
|
gClear(arguments_) {
|
|
577
512
|
return this.#execute("Can not clear.", (context) => {
|
|
@@ -583,89 +518,48 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
583
518
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
584
519
|
});
|
|
585
520
|
}
|
|
586
|
-
gClose() {
|
|
587
|
-
if (
|
|
588
|
-
if (
|
|
521
|
+
gClose(arguments_ = kei_lisp.Cons.nil) {
|
|
522
|
+
if (this.ctx === null) throw new kei_lisp.EvalError("Unable to initialize canvas. The browser or machine may not support it.");
|
|
523
|
+
if (arguments_.length() !== 0) throw new kei_lisp.EvalError("Can not close.");
|
|
524
|
+
if (!this.isOpen) throw new kei_lisp.EvalError("The canvas has already been closed.");
|
|
525
|
+
try {
|
|
589
526
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
590
|
-
this.isOpen = false;
|
|
591
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
592
527
|
} catch {
|
|
593
|
-
|
|
594
|
-
return kei_lisp.Cons.nil;
|
|
528
|
+
throw new kei_lisp.EvalError("Can not close.");
|
|
595
529
|
}
|
|
596
|
-
this
|
|
597
|
-
return kei_lisp.
|
|
530
|
+
this.isOpen = false;
|
|
531
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
598
532
|
}
|
|
599
533
|
gColor(arguments_) {
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
}
|
|
608
|
-
this.#print("Can not set color.");
|
|
609
|
-
return kei_lisp.Cons.nil;
|
|
610
|
-
} catch {
|
|
611
|
-
this.#print("Can not set color.");
|
|
612
|
-
return kei_lisp.Cons.nil;
|
|
613
|
-
}
|
|
614
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
615
|
-
return kei_lisp.Cons.nil;
|
|
534
|
+
return this.#execute("Can not set color.", (context) => {
|
|
535
|
+
if (arguments_.length() < 1) return null;
|
|
536
|
+
const aColor = this.selectColor(arguments_);
|
|
537
|
+
context.fillStyle = aColor;
|
|
538
|
+
context.strokeStyle = aColor;
|
|
539
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
540
|
+
});
|
|
616
541
|
}
|
|
617
|
-
gFill() {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
542
|
+
gFill(arguments_ = kei_lisp.Cons.nil) {
|
|
543
|
+
return this.#execute("Can not fill.", (context) => {
|
|
544
|
+
if (arguments_.length() !== 0) return null;
|
|
545
|
+
context.fill();
|
|
621
546
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
622
|
-
}
|
|
623
|
-
this.#print("Can not fill.");
|
|
624
|
-
return kei_lisp.Cons.nil;
|
|
625
|
-
}
|
|
626
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
627
|
-
return kei_lisp.Cons.nil;
|
|
547
|
+
});
|
|
628
548
|
}
|
|
629
549
|
gFillColor(arguments_) {
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
636
|
-
}
|
|
637
|
-
this.#print("Can not set fill color.");
|
|
638
|
-
return kei_lisp.Cons.nil;
|
|
639
|
-
} catch {
|
|
640
|
-
this.#print("Can not set fill color.");
|
|
641
|
-
return kei_lisp.Cons.nil;
|
|
642
|
-
}
|
|
643
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
644
|
-
return kei_lisp.Cons.nil;
|
|
550
|
+
return this.#execute("Can not set fill color.", (context) => {
|
|
551
|
+
if (arguments_.length() < 1) return null;
|
|
552
|
+
context.fillStyle = this.selectColor(arguments_);
|
|
553
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
554
|
+
});
|
|
645
555
|
}
|
|
646
556
|
gFillRect(arguments_) {
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
if (
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
const cdr2 = cdr1.cdr;
|
|
654
|
-
const a2 = cdr2.car;
|
|
655
|
-
const a3 = cdr2.cdr.car;
|
|
656
|
-
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2) && kei_lisp.Cons.isNumber(a3)) {
|
|
657
|
-
this.ctx.fillRect(a0, a1, a2, a3);
|
|
658
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
this.#print("Can not draw fill rectangle.");
|
|
662
|
-
return kei_lisp.Cons.nil;
|
|
663
|
-
} catch {
|
|
664
|
-
this.#print("Can not draw fill rectangle.");
|
|
665
|
-
return kei_lisp.Cons.nil;
|
|
666
|
-
}
|
|
667
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
668
|
-
return kei_lisp.Cons.nil;
|
|
557
|
+
return this.#execute("Can not draw fill rectangle.", (context) => {
|
|
558
|
+
const a = this.#numbers(arguments_, 4);
|
|
559
|
+
if (a === null) return null;
|
|
560
|
+
context.fillRect(a[0], a[1], a[2], a[3]);
|
|
561
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
562
|
+
});
|
|
669
563
|
}
|
|
670
564
|
gFillText(arguments_) {
|
|
671
565
|
return this.#execute("Can not draw fill text.", (context) => {
|
|
@@ -675,54 +569,29 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
675
569
|
if (!kei_lisp.Cons.isString(a0) || !kei_lisp.Cons.isNumber(a1) || !kei_lisp.Cons.isNumber(a2)) return null;
|
|
676
570
|
if (length_ === 4) {
|
|
677
571
|
if (!kei_lisp.Cons.isNumber(a3)) return null;
|
|
678
|
-
context.fillText(a0, a1, a2, a3);
|
|
679
|
-
} else context.fillText(a0, a1, a2);
|
|
572
|
+
context.fillText(a0, kei_lisp.Numeric.toFloat(a1), kei_lisp.Numeric.toFloat(a2), kei_lisp.Numeric.toFloat(a3));
|
|
573
|
+
} else context.fillText(a0, kei_lisp.Numeric.toFloat(a1), kei_lisp.Numeric.toFloat(a2));
|
|
680
574
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
681
575
|
});
|
|
682
576
|
}
|
|
683
577
|
gFillTri(arguments_) {
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
if (
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
const cdr4 = cdr3.cdr;
|
|
695
|
-
const a4 = cdr4.car;
|
|
696
|
-
const a5 = cdr4.cdr.car;
|
|
697
|
-
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)) {
|
|
698
|
-
this.ctx.beginPath();
|
|
699
|
-
this.ctx.moveTo(a0, a1);
|
|
700
|
-
this.ctx.lineTo(a2, a3);
|
|
701
|
-
this.ctx.lineTo(a4, a5);
|
|
702
|
-
this.ctx.fill();
|
|
703
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
this.#print("Can not draw fill triangle.");
|
|
707
|
-
return kei_lisp.Cons.nil;
|
|
708
|
-
} catch {
|
|
709
|
-
this.#print("Can not draw fill triangle.");
|
|
710
|
-
return kei_lisp.Cons.nil;
|
|
711
|
-
}
|
|
712
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
713
|
-
return kei_lisp.Cons.nil;
|
|
578
|
+
return this.#execute("Can not draw fill triangle.", (context) => {
|
|
579
|
+
const a = this.#numbers(arguments_, 6);
|
|
580
|
+
if (a === null) return null;
|
|
581
|
+
context.beginPath();
|
|
582
|
+
context.moveTo(a[0], a[1]);
|
|
583
|
+
context.lineTo(a[2], a[3]);
|
|
584
|
+
context.lineTo(a[4], a[5]);
|
|
585
|
+
context.fill();
|
|
586
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
587
|
+
});
|
|
714
588
|
}
|
|
715
|
-
gFinishPath() {
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
589
|
+
gFinishPath(arguments_ = kei_lisp.Cons.nil) {
|
|
590
|
+
return this.#execute("Can not finish path.", (context) => {
|
|
591
|
+
if (arguments_.length() !== 0) return null;
|
|
592
|
+
context.closePath();
|
|
719
593
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
720
|
-
}
|
|
721
|
-
this.#print("Can not finish path.");
|
|
722
|
-
return kei_lisp.Cons.nil;
|
|
723
|
-
}
|
|
724
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
725
|
-
return kei_lisp.Cons.nil;
|
|
594
|
+
});
|
|
726
595
|
}
|
|
727
596
|
gImage(arguments_) {
|
|
728
597
|
return this.#execute("Can not draw Image.", (context) => {
|
|
@@ -733,33 +602,21 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
733
602
|
if (length_ === 5) {
|
|
734
603
|
if (!kei_lisp.Cons.isNumber(a3) || !kei_lisp.Cons.isNumber(a4)) return null;
|
|
735
604
|
this.#withImage(a0, (image) => {
|
|
736
|
-
context.drawImage(image, a1, a2, a3, a4);
|
|
605
|
+
context.drawImage(image, kei_lisp.Numeric.toFloat(a1), kei_lisp.Numeric.toFloat(a2), kei_lisp.Numeric.toFloat(a3), kei_lisp.Numeric.toFloat(a4));
|
|
737
606
|
});
|
|
738
607
|
} else this.#withImage(a0, (image) => {
|
|
739
|
-
context.drawImage(image, a1, a2);
|
|
608
|
+
context.drawImage(image, kei_lisp.Numeric.toFloat(a1), kei_lisp.Numeric.toFloat(a2));
|
|
740
609
|
});
|
|
741
610
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
742
611
|
});
|
|
743
612
|
}
|
|
744
613
|
gLineTo(arguments_) {
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
if (
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
this.ctx.lineTo(a0, a1);
|
|
752
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
this.#print("Can not draw line to");
|
|
756
|
-
return kei_lisp.Cons.nil;
|
|
757
|
-
} catch {
|
|
758
|
-
this.#print("Can not draw line to");
|
|
759
|
-
return kei_lisp.Cons.nil;
|
|
760
|
-
}
|
|
761
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
762
|
-
return kei_lisp.Cons.nil;
|
|
614
|
+
return this.#execute("Can not draw line to", (context) => {
|
|
615
|
+
const a = this.#numbers(arguments_, 2);
|
|
616
|
+
if (a === null) return null;
|
|
617
|
+
context.lineTo(a[0], a[1]);
|
|
618
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
619
|
+
});
|
|
763
620
|
}
|
|
764
621
|
gLineCap(arguments_) {
|
|
765
622
|
return this.#execute("Can not set line cap. Expected \"butt\" / \"round\" / \"square\".", (context) => {
|
|
@@ -778,57 +635,35 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
778
635
|
});
|
|
779
636
|
}
|
|
780
637
|
gLineWidth(arguments_) {
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
if (
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
}
|
|
788
|
-
this.#print("Can not set line width.");
|
|
789
|
-
return kei_lisp.Cons.nil;
|
|
790
|
-
} catch {
|
|
791
|
-
this.#print("Can not set line width.");
|
|
792
|
-
return kei_lisp.Cons.nil;
|
|
793
|
-
}
|
|
794
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
795
|
-
return kei_lisp.Cons.nil;
|
|
638
|
+
return this.#execute("Can not set line width.", (context) => {
|
|
639
|
+
const a = this.#numbers(arguments_, 1);
|
|
640
|
+
if (a === null) return null;
|
|
641
|
+
context.lineWidth = a[0] <= 0 ? 1 : a[0];
|
|
642
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
643
|
+
});
|
|
796
644
|
}
|
|
797
645
|
gMoveTo(arguments_) {
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
if (
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
this.ctx.moveTo(a0, a1);
|
|
805
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
this.#print("Can not move");
|
|
809
|
-
return kei_lisp.Cons.nil;
|
|
810
|
-
} catch {
|
|
811
|
-
this.#print("Can not move");
|
|
812
|
-
return kei_lisp.Cons.nil;
|
|
813
|
-
}
|
|
814
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
815
|
-
return kei_lisp.Cons.nil;
|
|
646
|
+
return this.#execute("Can not move", (context) => {
|
|
647
|
+
const a = this.#numbers(arguments_, 2);
|
|
648
|
+
if (a === null) return null;
|
|
649
|
+
context.moveTo(a[0], a[1]);
|
|
650
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
651
|
+
});
|
|
816
652
|
}
|
|
817
|
-
gOpen() {
|
|
818
|
-
if (
|
|
819
|
-
if (
|
|
820
|
-
|
|
653
|
+
gOpen(arguments_ = kei_lisp.Cons.nil) {
|
|
654
|
+
if (this.ctx === null) throw new kei_lisp.EvalError("Unable to initialize canvas. The browser or machine may not support it.");
|
|
655
|
+
if (arguments_.length() !== 0) throw new kei_lisp.EvalError("Can not open.");
|
|
656
|
+
if (this.isOpen) throw new kei_lisp.EvalError("The canvas has already been opened.");
|
|
657
|
+
try {
|
|
821
658
|
this.ctx.fillStyle = "#ffffff";
|
|
822
659
|
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
|
823
660
|
this.ctx.fillStyle = "#000000";
|
|
824
|
-
this.#print(`canvas size, width : ${this.canvas.width} height : ${this.canvas.height}`);
|
|
825
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
826
661
|
} catch {
|
|
827
|
-
|
|
828
|
-
return kei_lisp.Cons.nil;
|
|
662
|
+
throw new kei_lisp.EvalError("Can not open.");
|
|
829
663
|
}
|
|
830
|
-
this
|
|
831
|
-
|
|
664
|
+
this.isOpen = true;
|
|
665
|
+
this.#print(`canvas size, width : ${this.canvas.width} height : ${this.canvas.height}`);
|
|
666
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
832
667
|
}
|
|
833
668
|
gPattern(arguments_) {
|
|
834
669
|
return this.#execute("Can not set pattern. Expected an image source and a repetition (\"repeat\" / \"repeat-x\" / \"repeat-y\" / \"no-repeat\").", (context) => {
|
|
@@ -847,28 +682,12 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
847
682
|
});
|
|
848
683
|
}
|
|
849
684
|
gQuadCurveTo(arguments_) {
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
if (
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
const cdr2 = cdr1.cdr;
|
|
857
|
-
const a2 = cdr2.car;
|
|
858
|
-
const a3 = cdr2.cdr.car;
|
|
859
|
-
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2) && kei_lisp.Cons.isNumber(a3)) {
|
|
860
|
-
this.ctx.quadraticCurveTo(a0, a1, a2, a3);
|
|
861
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
this.#print("Can not draw quadratic curve.");
|
|
865
|
-
return kei_lisp.Cons.nil;
|
|
866
|
-
} catch {
|
|
867
|
-
this.#print("Can not draw quadratic curve.");
|
|
868
|
-
return kei_lisp.Cons.nil;
|
|
869
|
-
}
|
|
870
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
871
|
-
return kei_lisp.Cons.nil;
|
|
685
|
+
return this.#execute("Can not draw quadratic curve.", (context) => {
|
|
686
|
+
const a = this.#numbers(arguments_, 4);
|
|
687
|
+
if (a === null) return null;
|
|
688
|
+
context.quadraticCurveTo(a[0], a[1], a[2], a[3]);
|
|
689
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
690
|
+
});
|
|
872
691
|
}
|
|
873
692
|
gSaveJpeg(arguments_) {
|
|
874
693
|
return this.saveCanvas(arguments_, "image/jpeg", "jpeg");
|
|
@@ -883,177 +702,91 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
883
702
|
* @param arguments_ - the evaluated argument list (empty, or one path string)
|
|
884
703
|
* @param mimeType - the image MIME type to encode
|
|
885
704
|
* @param label - the format name used in diagnostics ("jpeg" / "png")
|
|
886
|
-
* @return `t` on success
|
|
705
|
+
* @return `t` on success
|
|
887
706
|
*/
|
|
888
707
|
saveCanvas(arguments_, mimeType, label) {
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
this.#print(`Can not save ${label}.`);
|
|
895
|
-
return kei_lisp.Cons.nil;
|
|
896
|
-
}
|
|
897
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
898
|
-
return kei_lisp.Cons.nil;
|
|
708
|
+
this.#requireOpenContext();
|
|
709
|
+
const length_ = arguments_.length();
|
|
710
|
+
if (length_ === 0) return this.#downloadCanvas(mimeType, label);
|
|
711
|
+
if (length_ === 1 && kei_lisp.Cons.isString(arguments_.car)) return this.#writeCanvasToFile(arguments_.car, mimeType, label);
|
|
712
|
+
throw new kei_lisp.EvalError(`Can not save ${label}.`);
|
|
899
713
|
}
|
|
900
714
|
gScale(arguments_) {
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
if (
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
this.ctx.scale(a0, a1);
|
|
908
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
this.#print("Can not scale.");
|
|
912
|
-
return kei_lisp.Cons.nil;
|
|
913
|
-
} catch {
|
|
914
|
-
this.#print("Can not scale.");
|
|
915
|
-
return kei_lisp.Cons.nil;
|
|
916
|
-
}
|
|
917
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
918
|
-
return kei_lisp.Cons.nil;
|
|
715
|
+
return this.#execute("Can not scale.", (context) => {
|
|
716
|
+
const a = this.#numbers(arguments_, 2);
|
|
717
|
+
if (a === null) return null;
|
|
718
|
+
context.scale(a[0], a[1]);
|
|
719
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
720
|
+
});
|
|
919
721
|
}
|
|
920
722
|
gShadowBlur(arguments_) {
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
if (
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
this.#print("Can not set shadow blur.");
|
|
928
|
-
return kei_lisp.Cons.nil;
|
|
929
|
-
}
|
|
930
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
931
|
-
return kei_lisp.Cons.nil;
|
|
723
|
+
return this.#execute("Can not set shadow blur.", (context) => {
|
|
724
|
+
const a = this.#numbers(arguments_, 1);
|
|
725
|
+
if (a === null) return null;
|
|
726
|
+
context.shadowBlur = a[0];
|
|
727
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
728
|
+
});
|
|
932
729
|
}
|
|
933
730
|
gShadowColor(arguments_) {
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
940
|
-
}
|
|
941
|
-
this.#print("Can not set shadow color.");
|
|
942
|
-
return kei_lisp.Cons.nil;
|
|
943
|
-
} catch {
|
|
944
|
-
this.#print("Can not set shadow color.");
|
|
945
|
-
return kei_lisp.Cons.nil;
|
|
946
|
-
}
|
|
947
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
948
|
-
return kei_lisp.Cons.nil;
|
|
731
|
+
return this.#execute("Can not set shadow color.", (context) => {
|
|
732
|
+
if (arguments_.length() < 1) return null;
|
|
733
|
+
context.shadowColor = this.selectColor(arguments_);
|
|
734
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
735
|
+
});
|
|
949
736
|
}
|
|
950
737
|
gShadowOffsetX(arguments_) {
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
if (
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
this.#print("Can not set shadow offsetX.");
|
|
958
|
-
return kei_lisp.Cons.nil;
|
|
959
|
-
}
|
|
960
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
961
|
-
return kei_lisp.Cons.nil;
|
|
738
|
+
return this.#execute("Can not set shadow offsetX.", (context) => {
|
|
739
|
+
const a = this.#numbers(arguments_, 1);
|
|
740
|
+
if (a === null) return null;
|
|
741
|
+
context.shadowOffsetX = a[0];
|
|
742
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
743
|
+
});
|
|
962
744
|
}
|
|
963
745
|
gShadowOffsetY(arguments_) {
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
if (
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
this.#print("Can not set shadow offsetY.");
|
|
971
|
-
return kei_lisp.Cons.nil;
|
|
972
|
-
}
|
|
973
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
974
|
-
return kei_lisp.Cons.nil;
|
|
746
|
+
return this.#execute("Can not set shadow offsetY.", (context) => {
|
|
747
|
+
const a = this.#numbers(arguments_, 1);
|
|
748
|
+
if (a === null) return null;
|
|
749
|
+
context.shadowOffsetY = a[0];
|
|
750
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
751
|
+
});
|
|
975
752
|
}
|
|
976
753
|
gSleep(arguments_) {
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
sleep(arguments_.car);
|
|
985
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
986
|
-
}
|
|
987
|
-
this.#print("Can not sleep");
|
|
988
|
-
return kei_lisp.Cons.nil;
|
|
989
|
-
}
|
|
990
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
991
|
-
return kei_lisp.Cons.nil;
|
|
754
|
+
return this.#execute("Can not sleep", () => {
|
|
755
|
+
const a = this.#numbers(arguments_, 1);
|
|
756
|
+
if (a === null) return null;
|
|
757
|
+
const time = Date.now() + a[0];
|
|
758
|
+
while (Date.now() < time);
|
|
759
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
760
|
+
});
|
|
992
761
|
}
|
|
993
|
-
gStartPath() {
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
762
|
+
gStartPath(arguments_ = kei_lisp.Cons.nil) {
|
|
763
|
+
return this.#execute("Can not start path.", (context) => {
|
|
764
|
+
if (arguments_.length() !== 0) return null;
|
|
765
|
+
context.beginPath();
|
|
997
766
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
998
|
-
}
|
|
999
|
-
this.#print("Can not start path.");
|
|
1000
|
-
return kei_lisp.Cons.nil;
|
|
1001
|
-
}
|
|
1002
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
1003
|
-
return kei_lisp.Cons.nil;
|
|
767
|
+
});
|
|
1004
768
|
}
|
|
1005
|
-
gStroke() {
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
769
|
+
gStroke(arguments_ = kei_lisp.Cons.nil) {
|
|
770
|
+
return this.#execute("Can not stroke.", (context) => {
|
|
771
|
+
if (arguments_.length() !== 0) return null;
|
|
772
|
+
context.stroke();
|
|
1009
773
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
1010
|
-
}
|
|
1011
|
-
this.#print("Can not stroke.");
|
|
1012
|
-
return kei_lisp.Cons.nil;
|
|
1013
|
-
}
|
|
1014
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
1015
|
-
return kei_lisp.Cons.nil;
|
|
774
|
+
});
|
|
1016
775
|
}
|
|
1017
776
|
gStrokeColor(arguments_) {
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
1024
|
-
}
|
|
1025
|
-
this.#print("Can not set stroke color");
|
|
1026
|
-
return kei_lisp.Cons.nil;
|
|
1027
|
-
} catch {
|
|
1028
|
-
this.#print("Can not set stroke color");
|
|
1029
|
-
return kei_lisp.Cons.nil;
|
|
1030
|
-
}
|
|
1031
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
1032
|
-
return kei_lisp.Cons.nil;
|
|
777
|
+
return this.#execute("Can not set stroke color", (context) => {
|
|
778
|
+
if (arguments_.length() < 1) return null;
|
|
779
|
+
context.strokeStyle = this.selectColor(arguments_);
|
|
780
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
781
|
+
});
|
|
1033
782
|
}
|
|
1034
783
|
gStrokeRect(arguments_) {
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
if (
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
const cdr2 = cdr1.cdr;
|
|
1042
|
-
const a2 = cdr2.car;
|
|
1043
|
-
const a3 = cdr2.cdr.car;
|
|
1044
|
-
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2) && kei_lisp.Cons.isNumber(a3)) {
|
|
1045
|
-
this.ctx.strokeRect(a0, a1, a2, a3);
|
|
1046
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
this.#print("Can not draw stroke rectangle.");
|
|
1050
|
-
return kei_lisp.Cons.nil;
|
|
1051
|
-
} catch {
|
|
1052
|
-
this.#print("Can not draw stroke rectangle.");
|
|
1053
|
-
return kei_lisp.Cons.nil;
|
|
1054
|
-
}
|
|
1055
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
1056
|
-
return kei_lisp.Cons.nil;
|
|
784
|
+
return this.#execute("Can not draw stroke rectangle.", (context) => {
|
|
785
|
+
const a = this.#numbers(arguments_, 4);
|
|
786
|
+
if (a === null) return null;
|
|
787
|
+
context.strokeRect(a[0], a[1], a[2], a[3]);
|
|
788
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
789
|
+
});
|
|
1057
790
|
}
|
|
1058
791
|
gStrokeText(arguments_) {
|
|
1059
792
|
return this.#execute("Can not draw stroke text.", (context) => {
|
|
@@ -1063,43 +796,23 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
1063
796
|
if (!kei_lisp.Cons.isString(a0) || !kei_lisp.Cons.isNumber(a1) || !kei_lisp.Cons.isNumber(a2)) return null;
|
|
1064
797
|
if (length_ === 4) {
|
|
1065
798
|
if (!kei_lisp.Cons.isNumber(a3)) return null;
|
|
1066
|
-
context.strokeText(a0, a1, a2, a3);
|
|
1067
|
-
} else context.strokeText(a0, a1, a2);
|
|
799
|
+
context.strokeText(a0, kei_lisp.Numeric.toFloat(a1), kei_lisp.Numeric.toFloat(a2), kei_lisp.Numeric.toFloat(a3));
|
|
800
|
+
} else context.strokeText(a0, kei_lisp.Numeric.toFloat(a1), kei_lisp.Numeric.toFloat(a2));
|
|
1068
801
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
1069
802
|
});
|
|
1070
803
|
}
|
|
1071
804
|
gStrokeTri(arguments_) {
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
if (
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
const a4 = cdr4.car;
|
|
1084
|
-
const a5 = cdr4.cdr.car;
|
|
1085
|
-
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)) {
|
|
1086
|
-
this.ctx.beginPath();
|
|
1087
|
-
this.ctx.moveTo(a0, a1);
|
|
1088
|
-
this.ctx.lineTo(a2, a3);
|
|
1089
|
-
this.ctx.lineTo(a4, a5);
|
|
1090
|
-
this.ctx.closePath();
|
|
1091
|
-
this.ctx.stroke();
|
|
1092
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
this.#print("Can not draw stroke triangle.");
|
|
1096
|
-
return kei_lisp.Cons.nil;
|
|
1097
|
-
} catch {
|
|
1098
|
-
this.#print("Can not draw stroke triangle.");
|
|
1099
|
-
return kei_lisp.Cons.nil;
|
|
1100
|
-
}
|
|
1101
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
1102
|
-
return kei_lisp.Cons.nil;
|
|
805
|
+
return this.#execute("Can not draw stroke triangle.", (context) => {
|
|
806
|
+
const a = this.#numbers(arguments_, 6);
|
|
807
|
+
if (a === null) return null;
|
|
808
|
+
context.beginPath();
|
|
809
|
+
context.moveTo(a[0], a[1]);
|
|
810
|
+
context.lineTo(a[2], a[3]);
|
|
811
|
+
context.lineTo(a[4], a[5]);
|
|
812
|
+
context.closePath();
|
|
813
|
+
context.stroke();
|
|
814
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
815
|
+
});
|
|
1103
816
|
}
|
|
1104
817
|
gTextAlign(arguments_) {
|
|
1105
818
|
return this.#execute("Can not set text align. Expected \"left\" / \"right\" / \"center\" / \"start\" / \"end\".", (context) => {
|
|
@@ -1126,80 +839,35 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
1126
839
|
});
|
|
1127
840
|
}
|
|
1128
841
|
gTextFont(arguments_) {
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
}
|
|
1135
|
-
this.#print("Can not set text font.");
|
|
1136
|
-
return kei_lisp.Cons.nil;
|
|
1137
|
-
} catch {
|
|
1138
|
-
this.#print("Can not set text font.");
|
|
1139
|
-
return kei_lisp.Cons.nil;
|
|
1140
|
-
}
|
|
1141
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
1142
|
-
return kei_lisp.Cons.nil;
|
|
842
|
+
return this.#execute("Can not set text font.", (context) => {
|
|
843
|
+
if (arguments_.length() !== 1 || !kei_lisp.Cons.isString(arguments_.car)) return null;
|
|
844
|
+
context.font = arguments_.car;
|
|
845
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
846
|
+
});
|
|
1143
847
|
}
|
|
1144
848
|
gTranslate(arguments_) {
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
if (
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
this.ctx.translate(a0, a1);
|
|
1152
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
this.#print("Can not translate.");
|
|
1156
|
-
return kei_lisp.Cons.nil;
|
|
1157
|
-
} catch {
|
|
1158
|
-
this.#print("Can not translate.");
|
|
1159
|
-
return kei_lisp.Cons.nil;
|
|
1160
|
-
}
|
|
1161
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
1162
|
-
return kei_lisp.Cons.nil;
|
|
849
|
+
return this.#execute("Can not translate.", (context) => {
|
|
850
|
+
const a = this.#numbers(arguments_, 2);
|
|
851
|
+
if (a === null) return null;
|
|
852
|
+
context.translate(a[0], a[1]);
|
|
853
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
854
|
+
});
|
|
1163
855
|
}
|
|
1164
856
|
gRect(arguments_) {
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
if (
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
const cdr2 = cdr1.cdr;
|
|
1172
|
-
const a2 = cdr2.car;
|
|
1173
|
-
const a3 = cdr2.cdr.car;
|
|
1174
|
-
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2) && kei_lisp.Cons.isNumber(a3)) {
|
|
1175
|
-
this.ctx.rect(a0, a1, a2, a3);
|
|
1176
|
-
return kei_lisp.InterpretedSymbol.of("t");
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
this.#print("Can not draw rectangle.");
|
|
1180
|
-
return kei_lisp.Cons.nil;
|
|
1181
|
-
} catch {
|
|
1182
|
-
this.#print("Can not draw rectangle.");
|
|
1183
|
-
return kei_lisp.Cons.nil;
|
|
1184
|
-
}
|
|
1185
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
1186
|
-
return kei_lisp.Cons.nil;
|
|
857
|
+
return this.#execute("Can not draw rectangle.", (context) => {
|
|
858
|
+
const a = this.#numbers(arguments_, 4);
|
|
859
|
+
if (a === null) return null;
|
|
860
|
+
context.rect(a[0], a[1], a[2], a[3]);
|
|
861
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
862
|
+
});
|
|
1187
863
|
}
|
|
1188
864
|
gRotate(arguments_) {
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
if (
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
this.#print("Can not rotate.");
|
|
1196
|
-
return kei_lisp.Cons.nil;
|
|
1197
|
-
} catch {
|
|
1198
|
-
this.#print("Can not rotate.");
|
|
1199
|
-
return kei_lisp.Cons.nil;
|
|
1200
|
-
}
|
|
1201
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
1202
|
-
return kei_lisp.Cons.nil;
|
|
865
|
+
return this.#execute("Can not rotate.", (context) => {
|
|
866
|
+
const a = this.#numbers(arguments_, 1);
|
|
867
|
+
if (a === null) return null;
|
|
868
|
+
context.rotate(Math.PI / 180 * a[0]);
|
|
869
|
+
return kei_lisp.InterpretedSymbol.of("t");
|
|
870
|
+
});
|
|
1203
871
|
}
|
|
1204
872
|
/**
|
|
1205
873
|
* Pushes the current drawing state (styles, transform, clip) onto the
|
|
@@ -1207,36 +875,26 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
1207
875
|
* state explicitly. Replaces the legacy per-method `context.save()` calls, which
|
|
1208
876
|
* pushed state on every draw with no matching `restore()` and grew the stack
|
|
1209
877
|
* unbounded.
|
|
1210
|
-
* @return `t` on success
|
|
878
|
+
* @return `t` on success
|
|
1211
879
|
*/
|
|
1212
|
-
gSave() {
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
880
|
+
gSave(arguments_ = kei_lisp.Cons.nil) {
|
|
881
|
+
return this.#execute("Can not save.", (context) => {
|
|
882
|
+
if (arguments_.length() !== 0) return null;
|
|
883
|
+
context.save();
|
|
1216
884
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
1217
|
-
}
|
|
1218
|
-
this.#print("Can not save.");
|
|
1219
|
-
return kei_lisp.Cons.nil;
|
|
1220
|
-
}
|
|
1221
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
1222
|
-
return kei_lisp.Cons.nil;
|
|
885
|
+
});
|
|
1223
886
|
}
|
|
1224
887
|
/**
|
|
1225
888
|
* Pops the most recently saved drawing state off the context's state stack.
|
|
1226
889
|
* Pairs with `gSave`. Popping an empty stack is a no-op per the Canvas spec.
|
|
1227
|
-
* @return `t` on success
|
|
890
|
+
* @return `t` on success
|
|
1228
891
|
*/
|
|
1229
|
-
gRestore() {
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
892
|
+
gRestore(arguments_ = kei_lisp.Cons.nil) {
|
|
893
|
+
return this.#execute("Can not restore.", (context) => {
|
|
894
|
+
if (arguments_.length() !== 0) return null;
|
|
895
|
+
context.restore();
|
|
1233
896
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
1234
|
-
}
|
|
1235
|
-
this.#print("Can not restore.");
|
|
1236
|
-
return kei_lisp.Cons.nil;
|
|
1237
|
-
}
|
|
1238
|
-
this.#print("The canvas is closed and cannot be executed.");
|
|
1239
|
-
return kei_lisp.Cons.nil;
|
|
897
|
+
});
|
|
1240
898
|
}
|
|
1241
899
|
gEllipse(arguments_) {
|
|
1242
900
|
return this.#execute("Can not draw ellipse.", (context) => {
|
|
@@ -1258,6 +916,7 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
1258
916
|
return this.#execute("Can not set line dash.", (context) => {
|
|
1259
917
|
const segments = this.#numbers(arguments_, arguments_.length());
|
|
1260
918
|
if (segments === null) return null;
|
|
919
|
+
if (segments.some((segment) => !Number.isFinite(segment) || segment < 0)) return null;
|
|
1261
920
|
context.setLineDash(segments);
|
|
1262
921
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
1263
922
|
});
|
|
@@ -1278,8 +937,9 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
1278
937
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
1279
938
|
});
|
|
1280
939
|
}
|
|
1281
|
-
gClip() {
|
|
940
|
+
gClip(arguments_ = kei_lisp.Cons.nil) {
|
|
1282
941
|
return this.#execute("Can not clip.", (context) => {
|
|
942
|
+
if (arguments_.length() !== 0) return null;
|
|
1283
943
|
context.clip();
|
|
1284
944
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
1285
945
|
});
|
|
@@ -1314,8 +974,9 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
1314
974
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
1315
975
|
});
|
|
1316
976
|
}
|
|
1317
|
-
gResetTransform() {
|
|
977
|
+
gResetTransform(arguments_ = kei_lisp.Cons.nil) {
|
|
1318
978
|
return this.#execute("Can not reset transform.", (context) => {
|
|
979
|
+
if (arguments_.length() !== 0) return null;
|
|
1319
980
|
context.resetTransform();
|
|
1320
981
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
1321
982
|
});
|
|
@@ -1407,17 +1068,18 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
1407
1068
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
1408
1069
|
});
|
|
1409
1070
|
}
|
|
1410
|
-
gReset() {
|
|
1071
|
+
gReset(arguments_ = kei_lisp.Cons.nil) {
|
|
1411
1072
|
return this.#execute("Can not reset.", (context) => {
|
|
1073
|
+
if (arguments_.length() !== 0) return null;
|
|
1412
1074
|
context.reset();
|
|
1413
1075
|
return kei_lisp.InterpretedSymbol.of("t");
|
|
1414
1076
|
});
|
|
1415
1077
|
}
|
|
1416
|
-
gWidth() {
|
|
1417
|
-
return this.#execute("Can not get width.", () => this.canvas.width);
|
|
1078
|
+
gWidth(arguments_ = kei_lisp.Cons.nil) {
|
|
1079
|
+
return this.#execute("Can not get width.", () => arguments_.length() === 0 ? BigInt(this.canvas.width) : null);
|
|
1418
1080
|
}
|
|
1419
|
-
gHeight() {
|
|
1420
|
-
return this.#execute("Can not get height.", () => this.canvas.height);
|
|
1081
|
+
gHeight(arguments_ = kei_lisp.Cons.nil) {
|
|
1082
|
+
return this.#execute("Can not get height.", () => arguments_.length() === 0 ? BigInt(this.canvas.height) : null);
|
|
1421
1083
|
}
|
|
1422
1084
|
gPixel(arguments_) {
|
|
1423
1085
|
return this.#execute("Can not read pixel.", (context) => {
|
|
@@ -1425,10 +1087,10 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
1425
1087
|
if (a === null) return null;
|
|
1426
1088
|
const data = context.getImageData(a[0], a[1], 1, 1).data;
|
|
1427
1089
|
return this.#toList([
|
|
1428
|
-
data[0],
|
|
1429
|
-
data[1],
|
|
1430
|
-
data[2],
|
|
1431
|
-
data[3]
|
|
1090
|
+
BigInt(data[0]),
|
|
1091
|
+
BigInt(data[1]),
|
|
1092
|
+
BigInt(data[2]),
|
|
1093
|
+
BigInt(data[3])
|
|
1432
1094
|
]);
|
|
1433
1095
|
});
|
|
1434
1096
|
}
|
|
@@ -1449,27 +1111,28 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
1449
1111
|
return this.#execute("Can not set linear gradient.", (context) => {
|
|
1450
1112
|
const [x0, y0, x1, y1, ...stops] = this.#listValues(arguments_);
|
|
1451
1113
|
if (stops.length < 2 || !kei_lisp.Cons.isNumber(x0) || !kei_lisp.Cons.isNumber(y0) || !kei_lisp.Cons.isNumber(x1) || !kei_lisp.Cons.isNumber(y1)) return null;
|
|
1452
|
-
return this.#installGradient(context, context.createLinearGradient(x0, y0, x1, y1), stops);
|
|
1114
|
+
return this.#installGradient(context, context.createLinearGradient(kei_lisp.Numeric.toFloat(x0), kei_lisp.Numeric.toFloat(y0), kei_lisp.Numeric.toFloat(x1), kei_lisp.Numeric.toFloat(y1)), stops);
|
|
1453
1115
|
});
|
|
1454
1116
|
}
|
|
1455
1117
|
gRadialGradient(arguments_) {
|
|
1456
1118
|
return this.#execute("Can not set radial gradient.", (context) => {
|
|
1457
1119
|
const [x0, y0, r0, x1, y1, r1, ...stops] = this.#listValues(arguments_);
|
|
1458
1120
|
if (stops.length < 2 || !kei_lisp.Cons.isNumber(x0) || !kei_lisp.Cons.isNumber(y0) || !kei_lisp.Cons.isNumber(r0) || !kei_lisp.Cons.isNumber(x1) || !kei_lisp.Cons.isNumber(y1) || !kei_lisp.Cons.isNumber(r1)) return null;
|
|
1459
|
-
return this.#installGradient(context, context.createRadialGradient(x0, y0, r0, x1, y1, r1), stops);
|
|
1121
|
+
return this.#installGradient(context, context.createRadialGradient(kei_lisp.Numeric.toFloat(x0), kei_lisp.Numeric.toFloat(y0), kei_lisp.Numeric.toFloat(r0), kei_lisp.Numeric.toFloat(x1), kei_lisp.Numeric.toFloat(y1), kei_lisp.Numeric.toFloat(r1)), stops);
|
|
1460
1122
|
});
|
|
1461
1123
|
}
|
|
1462
1124
|
gConicGradient(arguments_) {
|
|
1463
1125
|
return this.#execute("Can not set conic gradient.", (context) => {
|
|
1464
1126
|
const [angle, x, y, ...stops] = this.#listValues(arguments_);
|
|
1465
1127
|
if (stops.length < 2 || !kei_lisp.Cons.isNumber(angle) || !kei_lisp.Cons.isNumber(x) || !kei_lisp.Cons.isNumber(y)) return null;
|
|
1466
|
-
return this.#installGradient(context, context.createConicGradient(Math.PI / 180 * angle, x, y), stops);
|
|
1128
|
+
return this.#installGradient(context, context.createConicGradient(Math.PI / 180 * kei_lisp.Numeric.toFloat(angle), kei_lisp.Numeric.toFloat(x), kei_lisp.Numeric.toFloat(y)), stops);
|
|
1467
1129
|
});
|
|
1468
1130
|
}
|
|
1469
1131
|
/**
|
|
1470
1132
|
* Parses a color spec from the head of the argument Cons. Accepts
|
|
1471
1133
|
* (1 string), (3 numbers — rgb), or (4 numbers — rgba); falls back to
|
|
1472
|
-
* `'black'` on anything else (legacy behavior
|
|
1134
|
+
* `'black'` on anything else (legacy behavior — a best-effort color parse
|
|
1135
|
+
* that prints a diagnostic instead of signaling an error).
|
|
1473
1136
|
* @param arguments_ - the argument Cons to parse
|
|
1474
1137
|
* @return CSS color string
|
|
1475
1138
|
*/
|
|
@@ -1482,7 +1145,7 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
1482
1145
|
const cdr1 = arguments_.cdr;
|
|
1483
1146
|
const a1 = cdr1.car;
|
|
1484
1147
|
const a2 = cdr1.cdr.car;
|
|
1485
|
-
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2)) aColor = `rgb(${a0}, ${a1}, ${a2})`;
|
|
1148
|
+
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2)) aColor = `rgb(${kei_lisp.Numeric.toFloat(a0)}, ${kei_lisp.Numeric.toFloat(a1)}, ${kei_lisp.Numeric.toFloat(a2)})`;
|
|
1486
1149
|
else this.#print("Can not set color. set color \"black\".");
|
|
1487
1150
|
} else if (length_ === 4) {
|
|
1488
1151
|
const cdr1 = arguments_.cdr;
|
|
@@ -1490,7 +1153,7 @@ var GraphicsPlugin = class GraphicsPlugin {
|
|
|
1490
1153
|
const cdr2 = cdr1.cdr;
|
|
1491
1154
|
const a2 = cdr2.car;
|
|
1492
1155
|
const a3 = cdr2.cdr.car;
|
|
1493
|
-
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})`;
|
|
1156
|
+
if (kei_lisp.Cons.isNumber(a0) && kei_lisp.Cons.isNumber(a1) && kei_lisp.Cons.isNumber(a2) && kei_lisp.Cons.isNumber(a3)) aColor = `rgba(${kei_lisp.Numeric.toFloat(a0)}, ${kei_lisp.Numeric.toFloat(a1)}, ${kei_lisp.Numeric.toFloat(a2)}, ${kei_lisp.Numeric.toFloat(a3)})`;
|
|
1494
1157
|
else this.#print("Can not set color. set color \"black\".");
|
|
1495
1158
|
} else this.#print("Can not set color. set color \"black\".");
|
|
1496
1159
|
return aColor;
|