@akashic/headless-driver 2.15.11 → 2.16.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/lib/Logger.js CHANGED
@@ -1,12 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getSystemLogger = exports.setSystemLogger = void 0;
3
+ exports.setSystemLogger = setSystemLogger;
4
+ exports.getSystemLogger = getSystemLogger;
4
5
  let _logger = console;
5
6
  function setSystemLogger(logger) {
6
7
  _logger = logger;
7
8
  }
8
- exports.setSystemLogger = setSystemLogger;
9
9
  function getSystemLogger() {
10
10
  return _logger;
11
11
  }
12
- exports.getSystemLogger = getSystemLogger;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createError = exports.TokenRevokedError = exports.RuntimeError = exports.BadRequestError = exports.TimeoutError = exports.NotImplementedError = exports.PermissionError = exports.InvalidStatusError = exports.AMFlowError = void 0;
3
+ exports.TokenRevokedError = exports.RuntimeError = exports.BadRequestError = exports.TimeoutError = exports.NotImplementedError = exports.PermissionError = exports.InvalidStatusError = exports.AMFlowError = void 0;
4
+ exports.createError = createError;
4
5
  class AMFlowError extends Error {
5
6
  constructor(message) {
6
7
  super(message);
@@ -99,4 +100,3 @@ function createError(type, message) {
99
100
  }
100
101
  return new RuntimeError(message);
101
102
  }
102
- exports.createError = createError;
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import type { AMFlow } from "@akashic/amflow";
3
2
  import { Trigger } from "@akashic/trigger";
4
3
  import { TimeKeeper } from "../TimeKeeper";
@@ -79,8 +79,8 @@ class Runner {
79
79
  * @param condition 進めるまでの条件となる関数。
80
80
  * @param timeout タイムアウトまでのミリ秒数。省略時は `5000` 。ゲーム内時間ではなく実時間である点に注意。
81
81
  */
82
- advanceUntil(condition, timeout = 5000) {
83
- return __awaiter(this, void 0, void 0, function* () {
82
+ advanceUntil(condition_1) {
83
+ return __awaiter(this, arguments, void 0, function* (condition, timeout = 5000) {
84
84
  return new Promise((resolve, reject) => {
85
85
  const limit = performance.now() + timeout;
86
86
  const handler = () => {
@@ -25,8 +25,9 @@ export interface CreateRunnerParameters {
25
25
  trusted?: boolean;
26
26
  /**
27
27
  * レンダリングモード。
28
- * `"canvas"` を指定するとプライマリサーフェスの描画内容を `Runner#getPrimarySurface()` を経由して取得できる。
28
+ * `"canvas"` または `"@napi-rs/canvas"` を指定するとプライマリサーフェスの描画内容を `Runner#getPrimarySurface()` を経由して取得できる。
29
29
  * `"canvas"` を指定した場合、利用側で node-canvas をインストールしなければならない。
30
+ * `"@napi-rs/canvas"` を指定した場合、利用側で @napi-rs/canvas をインストールしなければならない。
30
31
  * 初期値は `"none"` 。
31
32
  */
32
33
  renderingMode?: RunnerRenderingMode;
@@ -1,7 +1,19 @@
1
1
  import type { EncodingType } from "../utils";
2
2
  export type RunnerExecutionMode = "active" | "passive";
3
3
  export type RunnerLoopMode = "realtime" | "replay";
4
- export type RunnerRenderingMode = "none" | "canvas";
4
+ export type RunnerRenderingMode =
5
+ /**
6
+ * レンダリングを行わない。
7
+ */
8
+ "none"
9
+ /**
10
+ * node-canvas を使用する。
11
+ */
12
+ | "canvas"
13
+ /**
14
+ * @napi-rs/canvas を使用する。
15
+ */
16
+ | "@napi-rs/canvas";
5
17
  export type RunnerAdvanceConditionFunc = () => boolean;
6
18
  export interface RunnerPointEvent {
7
19
  type: "down" | "move" | "up";
@@ -1,10 +1,9 @@
1
- /** @ts-ignore */
2
- import type { Canvas } from "canvas";
3
1
  import type { RunnerStartParameters } from "../Runner";
4
2
  import { Runner } from "../Runner";
5
3
  import type { RunnerPointEvent } from "../types";
6
4
  import { akashicEngine as g, gameDriver as gdr } from "./engineFiles";
7
5
  import type { NodeCanvasSurface } from "./platform/graphics/canvas/NodeCanvasSurface";
6
+ import type { Canvas } from "./platform/graphics/canvas/types";
8
7
  import type { NullSurface } from "./platform/graphics/null/NullSurface";
9
8
  import { PlatformV3 } from "./platform/PlatformV3";
10
9
  export type RunnerV3Game = g.Game;
@@ -30,7 +29,7 @@ export declare class RunnerV3 extends Runner {
30
29
  getPrimarySurface(): NullSurface | NodeCanvasSurface;
31
30
  /**
32
31
  * プライマリサーフェスの Canvas インスタンスを取得する。
33
- * @returns node-canvas の Canvas
32
+ * @returns Canvas
34
33
  */
35
34
  getPrimarySurfaceCanvas(): Canvas;
36
35
  protected _stepMinimal(): void;
@@ -50,7 +50,7 @@ class RunnerV3 extends Runner_1.Runner {
50
50
  }
51
51
  pause() {
52
52
  if (this.platform == null) {
53
- this.errorTrigger.fire(new Error("Cannot call Runner#pause() before initialized"));
53
+ this.errorTrigger.fire(new Error("Cannot call Runner#pause() before initialization"));
54
54
  return;
55
55
  }
56
56
  this.platform.pauseLoopers();
@@ -59,7 +59,7 @@ class RunnerV3 extends Runner_1.Runner {
59
59
  }
60
60
  resume() {
61
61
  if (this.platform == null) {
62
- this.errorTrigger.fire(new Error("Cannot call Runner#resume() before initialized"));
62
+ this.errorTrigger.fire(new Error("Cannot call Runner#resume() before initialization"));
63
63
  return;
64
64
  }
65
65
  this.platform.resumeLoopers();
@@ -69,7 +69,7 @@ class RunnerV3 extends Runner_1.Runner {
69
69
  step() {
70
70
  return __awaiter(this, void 0, void 0, function* () {
71
71
  if (this.fps == null || this.platform == null) {
72
- this.errorTrigger.fire(new Error("Cannot call Runner#step() before initialized"));
72
+ this.errorTrigger.fire(new Error("Cannot call Runner#step() before initialization"));
73
73
  return;
74
74
  }
75
75
  if (this.running) {
@@ -88,11 +88,11 @@ class RunnerV3 extends Runner_1.Runner {
88
88
  advance(ms) {
89
89
  return __awaiter(this, void 0, void 0, function* () {
90
90
  if (this.fps == null || this.platform == null || this.driver == null) {
91
- this.errorTrigger.fire(new Error("Cannot call Runner#advance() before initialized"));
91
+ this.errorTrigger.fire(new Error("Cannot call Runner#advance() before initialization"));
92
92
  return;
93
93
  }
94
94
  if (this.running) {
95
- this.errorTrigger.fire(new Error("Cannot call Runner#advance() in running"));
95
+ this.errorTrigger.fire(new Error("Cannot call Runner#advance() while running"));
96
96
  return;
97
97
  }
98
98
  const loopConfiguration = this.driver.getLoopConfiguration();
@@ -128,7 +128,7 @@ class RunnerV3 extends Runner_1.Runner {
128
128
  }
129
129
  firePointEvent(event) {
130
130
  if (this.platform == null) {
131
- this.errorTrigger.fire(new Error("Cannot call Runner#firePointEvent() before initialized"));
131
+ this.errorTrigger.fire(new Error("Cannot call Runner#firePointEvent() before initialization"));
132
132
  return;
133
133
  }
134
134
  let type;
@@ -157,30 +157,27 @@ class RunnerV3 extends Runner_1.Runner {
157
157
  */
158
158
  getPrimarySurface() {
159
159
  if (!this.platform) {
160
- throw new Error("RunnerV3#getPrimarySurface(): Platform has not been initialized");
161
- }
162
- if (this.renderingMode === "canvas") {
163
- return this.platform.getPrimarySurface();
160
+ throw new Error("RunnerV3#getPrimarySurface(): Platform is not initialized");
164
161
  }
165
162
  return this.platform.getPrimarySurface();
166
163
  }
167
164
  /**
168
165
  * プライマリサーフェスの Canvas インスタンスを取得する。
169
- * @returns node-canvas の Canvas
166
+ * @returns Canvas
170
167
  */
171
168
  getPrimarySurfaceCanvas() {
172
- if (this.renderingMode !== "canvas") {
173
- throw Error("RunnerV3#getPrimarySurface(): Not supported except in the case of renderingMode === 'canvas");
169
+ if (this.renderingMode !== "canvas" && this.renderingMode !== "@napi-rs/canvas") {
170
+ throw Error("RunnerV3#getPrimarySurface(): Supported only when 'renderingMode' is 'canvas' or '@napi-rs/canvas'");
174
171
  }
175
172
  return this.getPrimarySurface()._drawable;
176
173
  }
177
174
  _stepMinimal() {
178
175
  if (this.fps == null || this.platform == null) {
179
- this.errorTrigger.fire(new Error("RunnerV3#_stepMinimal(): Cannot call Runner#step() before initialized"));
176
+ this.errorTrigger.fire(new Error("RunnerV3#_stepMinimal(): Cannot call Runner#step() before initialization"));
180
177
  return;
181
178
  }
182
179
  if (this.running) {
183
- this.errorTrigger.fire(new Error("RunnerV3#_stepMinimal(): Cannot call Runner#step() in running"));
180
+ this.errorTrigger.fire(new Error("RunnerV3#_stepMinimal(): Cannot call Runner#step() while running"));
184
181
  return;
185
182
  }
186
183
  // NOTE: 現状 PDI の API 仕様により this.step() では厳密なフレーム更新ができない。そこで、一フレームの 1/2 の時間で進行することでフレームが飛んでしまうことを防止する。
@@ -0,0 +1,10 @@
1
+ import type { RunnerRenderingMode } from "../../types";
2
+ import type { Canvas, Image } from "./graphics/canvas/types";
3
+ export declare class NodeCanvasFactory {
4
+ renderingMode: RunnerRenderingMode;
5
+ private module;
6
+ constructor(renderingMode: RunnerRenderingMode);
7
+ createCanvas(width: number, height: number): Canvas;
8
+ createImage(): Image;
9
+ _loadImage(filepath: string): Promise<Image>;
10
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NodeCanvasFactory = void 0;
4
+ class NodeCanvasFactory {
5
+ constructor(renderingMode) {
6
+ this.renderingMode = renderingMode;
7
+ // NOTE: このファイルの require() 時点で不要な依存モジュールを読み込ませないよう、動的に require() する。
8
+ // "canvas" と "@napi-rs/canvas" は (このライブラリで使う部分では) API が互換なのでそのまま流用している。
9
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
10
+ this.module = require(this.renderingMode === "canvas" ? "canvas" : "@napi-rs/canvas");
11
+ }
12
+ createCanvas(width, height) {
13
+ return this.module.createCanvas(width, height);
14
+ }
15
+ createImage() {
16
+ return new this.module.Image();
17
+ }
18
+ _loadImage(filepath) {
19
+ return new Promise((resolve, reject) => {
20
+ const img = this.createImage();
21
+ img.onload = () => {
22
+ resolve(img);
23
+ };
24
+ img.onerror = (err) => {
25
+ reject(err);
26
+ };
27
+ img.src = filepath;
28
+ });
29
+ }
30
+ }
31
+ exports.NodeCanvasFactory = NodeCanvasFactory;
@@ -1,18 +1,21 @@
1
1
  import type { RunnerLoadFileHandler } from "../../types";
2
2
  import type { akashicEngine as g } from "../engineFiles";
3
+ import type { NodeCanvasFactory } from "./NodeCanvasFactory";
3
4
  export interface NodeCanvasResourceFactoryParameters {
4
5
  loadFileHandler: RunnerLoadFileHandler;
5
6
  errorHandler: (err: Error) => void;
7
+ canvasFactory: NodeCanvasFactory;
6
8
  }
7
9
  /**
8
- * node-canvas への描画出力機能を持つ ResourceFactory の実装。
10
+ * 描画出力機能を持つ ResourceFactory の実装。
9
11
  * 音声再生には未対応。
10
12
  */
11
13
  export declare class NodeCanvasResourceFactory implements g.ResourceFactory {
12
14
  private loadFileHandler;
13
15
  private errorHandler;
14
- constructor({ loadFileHandler, errorHandler }: NodeCanvasResourceFactoryParameters);
15
- createImageAsset(id: string, assetPath: string, width: number, height: number): g.ImageAsset;
16
+ private canvasFactory;
17
+ constructor({ loadFileHandler, errorHandler, canvasFactory }: NodeCanvasResourceFactoryParameters);
18
+ createImageAsset(id: string, path: string, width: number, height: number): g.ImageAsset;
16
19
  createVideoAsset(id: string, assetPath: string, width: number, height: number, system: g.VideoSystem, loop: boolean, useRealSize: boolean): g.VideoAsset;
17
20
  createAudioAsset(id: string, assetPath: string, duration: number, system: g.AudioSystem, loop: boolean, hint: g.AudioAssetHint, offset?: number): g.AudioAsset;
18
21
  createAudioPlayer(system: g.AudioSystem): g.AudioPlayer;
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NodeCanvasResourceFactory = void 0;
4
- const canvas_1 = require("canvas");
5
4
  const NodeBinaryAsset_1 = require("./assets/NodeBinaryAsset");
6
5
  const NodeScriptAsset_1 = require("./assets/NodeScriptAsset");
7
6
  const NodeTextAsset_1 = require("./assets/NodeTextAsset");
@@ -12,16 +11,17 @@ const NodeCanvasImageAsset_1 = require("./graphics/canvas/NodeCanvasImageAsset")
12
11
  const NodeCanvasSurface_1 = require("./graphics/canvas/NodeCanvasSurface");
13
12
  const NullVideoAsset_1 = require("./videos/NullVideoAsset");
14
13
  /**
15
- * node-canvas への描画出力機能を持つ ResourceFactory の実装。
14
+ * 描画出力機能を持つ ResourceFactory の実装。
16
15
  * 音声再生には未対応。
17
16
  */
18
17
  class NodeCanvasResourceFactory {
19
- constructor({ loadFileHandler, errorHandler }) {
18
+ constructor({ loadFileHandler, errorHandler, canvasFactory }) {
20
19
  this.loadFileHandler = loadFileHandler;
21
20
  this.errorHandler = errorHandler;
21
+ this.canvasFactory = canvasFactory;
22
22
  }
23
- createImageAsset(id, assetPath, width, height) {
24
- return new NodeCanvasImageAsset_1.NodeCanvasImageAsset(id, assetPath, width, height);
23
+ createImageAsset(id, path, width, height) {
24
+ return new NodeCanvasImageAsset_1.NodeCanvasImageAsset({ canvasFactory: this.canvasFactory, id, path, width, height });
25
25
  }
26
26
  createVideoAsset(id, assetPath, width, height, system, loop, useRealSize) {
27
27
  return new NullVideoAsset_1.NullVideoAsset(id, assetPath, width, height, system, loop, useRealSize);
@@ -56,11 +56,11 @@ class NodeCanvasResourceFactory {
56
56
  });
57
57
  }
58
58
  createSurface(width, height) {
59
- const canvas = new canvas_1.Canvas(width, height);
59
+ const canvas = this.canvasFactory.createCanvas(width, height);
60
60
  return new NodeCanvasSurface_1.NodeCanvasSurface(canvas);
61
61
  }
62
62
  createGlyphFactory(fontFamily, fontSize, baselineHeight, fontColor, strokeWidth, strokeColor, strokeOnly, fontWeight) {
63
- return new NodeCanvasGlyphFactory_1.NodeCanvasGlyphFactory(fontFamily, fontSize, baselineHeight, fontColor, strokeWidth, strokeColor, strokeOnly, fontWeight);
63
+ return new NodeCanvasGlyphFactory_1.NodeCanvasGlyphFactory(this.canvasFactory, fontFamily, fontSize, baselineHeight, fontColor, strokeWidth, strokeColor, strokeOnly, fontWeight);
64
64
  }
65
65
  }
66
66
  exports.NodeCanvasResourceFactory = NodeCanvasResourceFactory;
@@ -12,34 +12,40 @@ class PlatformV3 extends Platform_1.Platform {
12
12
  this.eventHandler = null;
13
13
  this.loopers = [];
14
14
  this.isLooperPaused = false;
15
+ let resourceFactory;
15
16
  // NOTE: このファイルの require() 時点で ResourceFactory 側の依存モジュールを読み込ませないよう、動的に require() する。
16
- // (このモジュールの利用元である headless-driver が NodeVM 上で起動する仕様上の制限のための苦肉の策)
17
17
  /* eslint-disable @typescript-eslint/naming-convention, @typescript-eslint/no-var-requires */
18
- const ResourceFactory = this.renderingMode === "canvas" && this.trusted
19
- ? require("./NodeCanvasResourceFactory").NodeCanvasResourceFactory
20
- : require("./NullResourceFactory").NullResourceFactory;
21
- /* eslint-enable */
22
- this.resFac = new ResourceFactory({
23
- errorHandler: (e) => this.errorHandler(e),
24
- loadFileHandler: param.loadFileHandler
25
- });
18
+ if ((this.renderingMode === "canvas" || this.renderingMode === "@napi-rs/canvas") && this.trusted) {
19
+ const ResourceFactory = require("./NodeCanvasResourceFactory").NodeCanvasResourceFactory;
20
+ const NodeCanvasFactory = require("./NodeCanvasFactory").NodeCanvasFactory;
21
+ const canvasFactory = new NodeCanvasFactory(this.renderingMode);
22
+ resourceFactory = new ResourceFactory({
23
+ canvasFactory,
24
+ errorHandler: (e) => this.errorHandler(e),
25
+ loadFileHandler: param.loadFileHandler
26
+ });
27
+ }
28
+ else {
29
+ const ResourceFactory = require("./NullResourceFactory").NullResourceFactory;
30
+ resourceFactory = new ResourceFactory({
31
+ errorHandler: (e) => this.errorHandler(e),
32
+ loadFileHandler: param.loadFileHandler
33
+ });
34
+ }
35
+ /* eslint-enable @typescript-eslint/naming-convention, @typescript-eslint/no-var-requires */
36
+ this.resFac = resourceFactory;
26
37
  }
27
38
  getResourceFactory() {
28
39
  return this.resFac;
29
40
  }
30
41
  setRendererRequirement(requirement) {
31
42
  this.rendererReq = requirement;
32
- if (this.renderingMode === "canvas") {
43
+ if (this.renderingMode === "canvas" || this.renderingMode === "@napi-rs/canvas") {
33
44
  if (this.trusted) {
34
- /* eslint-disable @typescript-eslint/naming-convention, @typescript-eslint/no-var-requires */
35
- const Canvas = require("canvas").Canvas;
36
- const NodeCanvasSurface = require("./graphics/canvas/NodeCanvasSurface").NodeCanvasSurface;
37
- /* eslint-enable */
38
- const canvas = new Canvas(this.rendererReq.primarySurfaceWidth, this.rendererReq.primarySurfaceHeight);
39
- this.primarySurface = new NodeCanvasSurface(canvas);
45
+ this.primarySurface = this.resFac.createSurface(this.rendererReq.primarySurfaceWidth, this.rendererReq.primarySurfaceHeight);
40
46
  }
41
47
  else {
42
- throw Error("PlatformV3#setRendererRequirement(): Must given trusted === `true` if set renderingMode === 'canvas'");
48
+ throw Error("PlatformV3#setRendererRequirement(): 'trusted' must be true when 'renderingMode' is set to 'canvas' or '@napi-rs/canvas'.");
43
49
  }
44
50
  }
45
51
  else {
@@ -1,7 +1,6 @@
1
- /** @ts-ignore */
2
- import type { CanvasRenderingContext2D, ImageData } from "canvas";
3
1
  import type { akashicEngine as g } from "../../../engineFiles";
4
2
  import { RenderingState } from "./RenderingState";
3
+ import type { CanvasRenderingContext2D, ImageData } from "./types";
5
4
  export declare class NodeCanvasContext {
6
5
  protected _context: CanvasRenderingContext2D;
7
6
  protected _stateStack: RenderingState[];
@@ -1,4 +1,5 @@
1
1
  import type { akashicEngine as g } from "../../../engineFiles";
2
+ import type { NodeCanvasFactory } from "../../NodeCanvasFactory";
2
3
  export declare class NodeCanvasGlyphFactory implements g.GlyphFactory {
3
4
  /**
4
5
  * 実行環境が描画可能な最小フォントサイズ
@@ -18,7 +19,8 @@ export declare class NodeCanvasGlyphFactory implements g.GlyphFactory {
18
19
  _marginW: number;
19
20
  _marginH: number;
20
21
  _cssFontFamily: string;
21
- constructor(fontFamily: string | string[], fontSize: number, baselineHeight?: number, fontColor?: string, strokeWidth?: number, strokeColor?: string, strokeOnly?: boolean, fontWeight?: g.FontWeightString);
22
+ _canvasFactory: NodeCanvasFactory;
23
+ constructor(canvasFactory: NodeCanvasFactory, fontFamily: string | string[], fontSize: number, baselineHeight?: number, fontColor?: string, strokeWidth?: number, strokeColor?: string, strokeOnly?: boolean, fontWeight?: g.FontWeightString);
22
24
  create(code: number): g.Glyph;
23
25
  measureMinimumFontSize(): number;
24
26
  }
@@ -1,10 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NodeCanvasGlyphFactory = void 0;
4
- const canvas_1 = require("canvas");
5
4
  const NodeCanvasGlyph_1 = require("./NodeCanvasGlyph");
6
5
  const NodeCanvasSurface_1 = require("./NodeCanvasSurface");
7
- function createGlyphRenderedSurface(code, fontSize, cssFontFamily, baselineHeight, marginW, marginH, needImageData, fontColor, strokeWidth, strokeColor, strokeOnly, fontWeight) {
6
+ function createGlyphRenderedSurface(canvasFactory, code, fontSize, cssFontFamily, baselineHeight, marginW, marginH, needImageData, fontColor, strokeWidth, strokeColor, strokeOnly, fontWeight) {
8
7
  // 要求されたフォントサイズが描画可能な最小フォントサイズ以下だった場合、必要なスケーリング係数
9
8
  const scale = fontSize < NodeCanvasGlyphFactory._environmentMinimumFontSize ? fontSize / NodeCanvasGlyphFactory._environmentMinimumFontSize : 1;
10
9
  const surfaceWidth = Math.ceil((fontSize + marginW * 2) * scale);
@@ -13,7 +12,7 @@ function createGlyphRenderedSurface(code, fontSize, cssFontFamily, baselineHeigh
13
12
  // 理由:
14
13
  // * Renderer#drawSystemText()を廃止または非推奨にしたいのでそれを用いず文字列を描画する
15
14
  // * RenderingHelperがcontextの状態を復帰するためTextMetricsを取れない
16
- const canvas = new canvas_1.Canvas(surfaceWidth, surfaceHeight);
15
+ const canvas = canvasFactory.createCanvas(surfaceWidth, surfaceHeight);
17
16
  const context = canvas.getContext("2d");
18
17
  const str = code & 0xffff0000 ? String.fromCharCode((code & 0xffff0000) >>> 16, code & 0xffff) : String.fromCharCode(code);
19
18
  const fontWeightValue = fontWeight === "bold" ? "bold " : "";
@@ -120,7 +119,7 @@ function fontFamily2CSSFontFamily(fontFamily) {
120
119
  }
121
120
  }
122
121
  class NodeCanvasGlyphFactory {
123
- constructor(fontFamily, fontSize, baselineHeight = fontSize, fontColor = "black", strokeWidth = 0, strokeColor = "black", strokeOnly = false, fontWeight = "normal") {
122
+ constructor(canvasFactory, fontFamily, fontSize, baselineHeight = fontSize, fontColor = "black", strokeWidth = 0, strokeColor = "black", strokeOnly = false, fontWeight = "normal") {
124
123
  this.fontFamily = fontFamily;
125
124
  this.fontSize = fontSize;
126
125
  this.fontWeight = fontWeight;
@@ -129,6 +128,7 @@ class NodeCanvasGlyphFactory {
129
128
  this.strokeWidth = strokeWidth;
130
129
  this.strokeColor = strokeColor;
131
130
  this.strokeOnly = strokeOnly;
131
+ this._canvasFactory = canvasFactory;
132
132
  this._glyphAreas = {};
133
133
  this._cssFontFamily = fontFamily2CSSFontFamily(fontFamily);
134
134
  // Akashicエンジンは指定されたフォントに利用可能なものが見つからない時
@@ -155,7 +155,7 @@ class NodeCanvasGlyphFactory {
155
155
  let result = null;
156
156
  let glyphArea = this._glyphAreas[code];
157
157
  if (!glyphArea) {
158
- result = createGlyphRenderedSurface(code, this.fontSize, this._cssFontFamily, this.baselineHeight, this._marginW, this._marginH, true, this.fontColor, this.strokeWidth, this.strokeColor, this.strokeOnly, this.fontWeight);
158
+ result = createGlyphRenderedSurface(this._canvasFactory, code, this.fontSize, this._cssFontFamily, this.baselineHeight, this._marginW, this._marginH, true, this.fontColor, this.strokeWidth, this.strokeColor, this.strokeOnly, this.fontWeight);
159
159
  glyphArea = calcGlyphArea(result.imageData); // NOTE: `needImageData` が true のため必ず真
160
160
  glyphArea.advanceWidth = result.advanceWidth;
161
161
  this._glyphAreas[code] = glyphArea;
@@ -172,7 +172,7 @@ class NodeCanvasGlyphFactory {
172
172
  // サーフェスを生成する。もし前段でcalcGlyphArea()のためのサーフェスを生成して
173
173
  // いればここでは生成せずにそれを利用する。
174
174
  if (!result) {
175
- result = createGlyphRenderedSurface(code, this.fontSize, this._cssFontFamily, this.baselineHeight, this._marginW, this._marginH, false, this.fontColor, this.strokeWidth, this.strokeColor, this.strokeOnly, this.fontWeight);
175
+ result = createGlyphRenderedSurface(this._canvasFactory, code, this.fontSize, this._cssFontFamily, this.baselineHeight, this._marginW, this._marginH, false, this.fontColor, this.strokeWidth, this.strokeColor, this.strokeOnly, this.fontWeight);
176
176
  }
177
177
  return new NodeCanvasGlyph_1.NodeCanvasGlyph(code, glyphArea.x, glyphArea.y, (_a = glyphArea.width) !== null && _a !== void 0 ? _a : 0, (_b = glyphArea.height) !== null && _b !== void 0 ? _b : 0, glyphArea.x - this._marginW, glyphArea.y - this._marginH, glyphArea.advanceWidth, result.surface, true);
178
178
  }
@@ -181,7 +181,7 @@ class NodeCanvasGlyphFactory {
181
181
  measureMinimumFontSize() {
182
182
  let fontSize = 1;
183
183
  const str = "M";
184
- const canvas = new canvas_1.Canvas(50, 50);
184
+ const canvas = this._canvasFactory.createCanvas(50, 50);
185
185
  const context = canvas.getContext("2d");
186
186
  if (context == null) {
187
187
  throw new Error("cannot get canvas context");
@@ -1,5 +1,13 @@
1
1
  import type { akashicEngine as g } from "../../../engineFiles";
2
2
  import { Asset } from "../../assets/Asset";
3
+ import type { NodeCanvasFactory } from "../../NodeCanvasFactory";
4
+ export interface NodeCanvasImageAssetParameters {
5
+ id: string;
6
+ path: string;
7
+ width: number;
8
+ height: number;
9
+ canvasFactory: NodeCanvasFactory;
10
+ }
3
11
  export declare class NodeCanvasImageAsset extends Asset implements g.ImageAsset {
4
12
  type: "image";
5
13
  width: number;
@@ -8,7 +16,8 @@ export declare class NodeCanvasImageAsset extends Asset implements g.ImageAsset
8
16
  _surface: g.Surface | null;
9
17
  private data;
10
18
  private dataCache;
11
- constructor(id: string, path: string, width: number, height: number);
19
+ private canvasFactory;
20
+ constructor(param: NodeCanvasImageAssetParameters);
12
21
  destroy(): void;
13
22
  _load(loader: g.AssetLoadHandler): void;
14
23
  asSurface(): g.Surface;
@@ -1,18 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NodeCanvasImageAsset = void 0;
4
- const canvas_1 = require("canvas");
5
4
  const Asset_1 = require("../../assets/Asset");
6
5
  const NodeCanvasSurface_1 = require("./NodeCanvasSurface");
7
6
  class NodeCanvasImageAsset extends Asset_1.Asset {
8
- constructor(id, path, width, height) {
9
- super(id, path);
7
+ constructor(param) {
8
+ super(param.id, param.path);
10
9
  this.type = "image";
11
10
  this._surface = null;
12
11
  this.data = null;
13
12
  this.dataCache = null;
14
- this.width = width;
15
- this.height = height;
13
+ this.width = param.width;
14
+ this.height = param.height;
15
+ this.canvasFactory = param.canvasFactory;
16
16
  }
17
17
  destroy() {
18
18
  if (this._surface && !this._surface.destroyed()) {
@@ -35,7 +35,7 @@ class NodeCanvasImageAsset extends Asset_1.Asset {
35
35
  loader._onAssetLoad(this);
36
36
  }
37
37
  else {
38
- const image = new canvas_1.Image();
38
+ const image = this.canvasFactory.createImage();
39
39
  image.onerror = () => {
40
40
  loader._onAssetError(this, {
41
41
  name: "AssetLoadError",
@@ -64,7 +64,7 @@ class NodeCanvasImageAsset extends Asset_1.Asset {
64
64
  throw new Error("NodeCanvasImageAsset#asSurface(): not yet loaded.");
65
65
  }
66
66
  if (this._surface == null) {
67
- const canvas = new canvas_1.Canvas(this.width, this.height);
67
+ const canvas = this.canvasFactory.createCanvas(this.width, this.height);
68
68
  const context = canvas.getContext("2d");
69
69
  context.drawImage(this.data, 0, 0, this.width, this.height);
70
70
  this._surface = new NodeCanvasSurface_1.NodeCanvasSurface(canvas);
@@ -1,7 +1,6 @@
1
- /** @ts-ignore */
2
- import type { ImageData } from "canvas";
3
1
  import type { akashicEngine as g } from "../../../engineFiles";
4
2
  import type { NodeCanvasContext } from "./NodeCanvasContext";
3
+ import type { ImageData } from "./types";
5
4
  export declare class NodeCanvasRenderer implements g.Renderer {
6
5
  private context;
7
6
  private width;
@@ -1,7 +1,6 @@
1
- /** @ts-ignore */
2
- import type { Canvas } from "canvas";
3
1
  import type { akashicEngine as g } from "../../../engineFiles";
4
2
  import { NodeCanvasRenderer } from "./NodeCanvasRenderer";
3
+ import type { Canvas } from "./types";
5
4
  export declare class NodeCanvasSurface implements g.Surface {
6
5
  width: number;
7
6
  height: number;
@@ -0,0 +1,2 @@
1
+ /** @ts-ignore */
2
+ export type { Canvas, Image, CanvasRenderingContext2D, ImageData, GlobalCompositeOperation } from "canvas";
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ // NOTE: node-canvas ライブラリを利用しない環境で型定義の参照に失敗するケースを回避するため、 `@ts-ignore` で明示的にエラーを無視している
3
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.requireEngineFiles = void 0;
3
+ exports.requireEngineFiles = requireEngineFiles;
4
4
  const fs = require("fs");
5
5
  const path = require("path");
6
6
  /**
@@ -18,4 +18,3 @@ function requireEngineFiles() {
18
18
  }
19
19
  return undefined;
20
20
  }
21
- exports.requireEngineFiles = requireEngineFiles;
package/lib/utils.js CHANGED
@@ -9,13 +9,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.resolveUrl = exports.isHttpProtocol = exports.LoadFileInternal = exports.loadFile = void 0;
12
+ exports.LoadFileInternal = void 0;
13
+ exports.loadFile = loadFile;
14
+ exports.isHttpProtocol = isHttpProtocol;
15
+ exports.resolveUrl = resolveUrl;
13
16
  const fs = require("fs");
14
17
  const node_fetch_1 = require("node-fetch");
15
18
  const waitings = [];
16
19
  let loadingCount = 0;
17
- function loadFile(url, encoding = "utf-8") {
18
- return __awaiter(this, void 0, void 0, function* () {
20
+ function loadFile(url_1) {
21
+ return __awaiter(this, arguments, void 0, function* (url, encoding = "utf-8") {
19
22
  const promise = new Promise((resolve, reject) => {
20
23
  waitings.push({ url, encoding, resolve, reject });
21
24
  });
@@ -23,7 +26,6 @@ function loadFile(url, encoding = "utf-8") {
23
26
  return promise;
24
27
  });
25
28
  }
26
- exports.loadFile = loadFile;
27
29
  function processWaitingLoad() {
28
30
  return __awaiter(this, void 0, void 0, function* () {
29
31
  if (loadingCount >= LoadFileInternal.MAX_PARALLEL_LOAD || waitings.length === 0)
@@ -54,8 +56,8 @@ var LoadFileInternal;
54
56
  * 具体的な値は調整の余地がある。少なくとも Windows 環境で、128 以上で問題が起きることがわかっている。
55
57
  */
56
58
  LoadFileInternal.MAX_PARALLEL_LOAD = 32;
57
- function loadImpl(url, encoding = "utf-8") {
58
- return __awaiter(this, void 0, void 0, function* () {
59
+ function loadImpl(url_1) {
60
+ return __awaiter(this, arguments, void 0, function* (url, encoding = "utf-8") {
59
61
  if (isHttpProtocol(url)) {
60
62
  const res = yield (0, node_fetch_1.default)(url, { method: "GET" });
61
63
  if (encoding === "utf-8") {
@@ -86,7 +88,6 @@ var LoadFileInternal;
86
88
  function isHttpProtocol(url) {
87
89
  return /^(http|https)\:\/\//.test(url);
88
90
  }
89
- exports.isHttpProtocol = isHttpProtocol;
90
91
  // @see https://nodejs.org/api/url.html#urlresolvefrom-to
91
92
  function resolveUrl(from, to) {
92
93
  const resolvedUrl = new URL(to, new URL(from, "resolve://"));
@@ -97,4 +98,3 @@ function resolveUrl(from, to) {
97
98
  }
98
99
  return resolvedUrl.toString();
99
100
  }
100
- exports.resolveUrl = resolveUrl;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akashic/headless-driver",
3
- "version": "2.15.11",
3
+ "version": "2.16.0",
4
4
  "description": "A library to execute contents using Akashic Engine headlessly",
5
5
  "main": "lib/index.js",
6
6
  "author": "DWANGO Co., Ltd.",
@@ -29,7 +29,7 @@
29
29
  "@akashic/trigger": "^2.0.0",
30
30
  "engine-files-v1": "npm:@akashic/engine-files@1.4.0",
31
31
  "engine-files-v2": "npm:@akashic/engine-files@2.4.0",
32
- "engine-files-v3": "npm:@akashic/engine-files@3.10.1",
32
+ "engine-files-v3": "npm:@akashic/engine-files@3.11.0",
33
33
  "js-sha256": "^0.11.0",
34
34
  "lodash.clonedeep": "^4.5.0",
35
35
  "node-fetch": "^2.6.7"
@@ -37,6 +37,7 @@
37
37
  "devDependencies": {
38
38
  "@akashic/eslint-config": "^2.0.0",
39
39
  "@akashic/remark-preset-lint": "^0.1.2",
40
+ "@napi-rs/canvas": "^0.1.66",
40
41
  "@types/jest": "^29.1.1",
41
42
  "@types/lodash.clonedeep": "^4.5.7",
42
43
  "@types/node": "^18.7.23",
@@ -44,7 +45,7 @@
44
45
  "@types/pixelmatch": "^5.2.4",
45
46
  "@types/pngjs": "^6.0.1",
46
47
  "@typescript-eslint/eslint-plugin": "^6.12.0",
47
- "canvas": "^2.11.2",
48
+ "canvas": "^3.1.0",
48
49
  "eslint": "^8.54.0",
49
50
  "eslint-config-prettier": "^9.0.0",
50
51
  "eslint-plugin-import": "^2.29.0",
@@ -59,8 +60,8 @@
59
60
  "remark-cli": "^12.0.0",
60
61
  "rimraf": "^6.0.0",
61
62
  "serve-handler": "^6.1.3",
62
- "ts-jest": "^29.0.3",
63
- "typescript": "^5.0.0"
63
+ "ts-jest": "^29.2.5",
64
+ "typescript": "^5.7.3"
64
65
  },
65
66
  "jest": {
66
67
  "moduleFileExtensions": [