@next2d/builder 0.1.7 → 0.1.10
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/dist/cli.d.ts +59 -0
- package/dist/cli.js +141 -0
- package/dist/constants.d.ts +53 -0
- package/dist/constants.js +64 -0
- package/dist/context.d.ts +29 -0
- package/dist/context.js +19 -0
- package/dist/electron.d.ts +10 -0
- package/dist/electron.js +142 -0
- package/dist/index.js +18 -754
- package/dist/native.d.ts +27 -0
- package/dist/native.js +123 -0
- package/dist/utils.d.ts +27 -0
- package/dist/utils.js +40 -0
- package/dist/web.d.ts +18 -0
- package/dist/web.js +70 -0
- package/dist/xbox.d.ts +62 -0
- package/dist/xbox.js +426 -0
- package/package.json +12 -9
- package/templates/xbox/CMakeLists.txt +116 -11
- package/templates/xbox/README.md +34 -8
- package/templates/xbox/cmake/FetchDawn.cmake +47 -6
- package/templates/xbox/cmake/FindV8.cmake +15 -0
- package/templates/xbox/js/bootstrap.js +151 -28
- package/templates/xbox/js/selftest.js +740 -90
- package/templates/xbox/src/AssetLoader.cpp +115 -12
- package/templates/xbox/src/AssetLoader.h +4 -0
- package/templates/xbox/src/EmbeddedAssets.cpp +149 -0
- package/templates/xbox/src/EmbeddedAssets.h +60 -0
- package/templates/xbox/src/EventLoop.cpp +13 -1
- package/templates/xbox/src/EventLoop.h +12 -0
- package/templates/xbox/src/bindings/Audio.cpp +211 -31
- package/templates/xbox/src/bindings/Bindings.h +10 -0
- package/templates/xbox/src/bindings/Canvas.cpp +77 -2
- package/templates/xbox/src/bindings/Canvas2D.cpp +496 -43
- package/templates/xbox/src/bindings/Console.cpp +6 -1
- package/templates/xbox/src/bindings/DomShims.cpp +143 -0
- package/templates/xbox/src/bindings/EventTarget.cpp +11 -0
- package/templates/xbox/src/bindings/Fetch.cpp +2 -8
- package/templates/xbox/src/bindings/Image.cpp +243 -15
- package/templates/xbox/src/bindings/Polyfills.cpp +1226 -0
- package/templates/xbox/src/bindings/RasterCore.h +105 -1
- package/templates/xbox/src/bindings/Video.cpp +153 -10
- package/templates/xbox/src/bindings/webgpu/WebGPU.cpp +844 -18
- package/templates/xbox/src/bindings/webgpu/WebGPUCommon.h +7 -9
- package/templates/xbox/src/bindings/webgpu/WebGPUEnums.h +32 -0
- package/templates/xbox/src/gpu/DawnContext.cpp +245 -7
- package/templates/xbox/src/gpu/DawnContext.h +18 -0
- package/templates/xbox/src/main.cpp +459 -8
- package/templates/xbox/src/platform/AudioDecoder.cpp +121 -0
- package/templates/xbox/src/platform/AudioDecoder.h +18 -0
- package/templates/xbox/src/platform/AudioEngine.cpp +37 -6
- package/templates/xbox/src/platform/DecodeQueue.cpp +136 -0
- package/templates/xbox/src/platform/DecodeQueue.h +27 -0
- package/templates/xbox/src/platform/ImageDecoder.cpp +44 -0
- package/templates/xbox/src/platform/ImageDecoder.h +18 -0
- package/templates/xbox/src/platform/StbTextRasterizer.cpp +324 -0
- package/templates/xbox/src/platform/StbTextRasterizer.h +37 -0
- package/templates/xbox/src/platform/TextRasterizer.cpp +32 -0
- package/templates/xbox/src/platform/WicDecoder.cpp +19 -0
- package/templates/xbox/src/v8/CodeCache.h +223 -0
- package/templates/xbox/src/v8/V8Runtime.cpp +76 -11
- package/templates/xbox/src/v8/V8Util.h +79 -0
- package/templates/xbox/src/v8/WeakHandle.h +45 -0
- package/templates/xbox/src/worker/WorkerRuntime.cpp +432 -48
- package/templates/xbox/src/worker/WorkerRuntime.h +43 -13
- package/templates/xbox/tests/check_local.sh +7 -2
- package/templates/xbox/tests/gamecore_api_probe.cpp +172 -0
- package/templates/xbox/tests/raster_test.cpp +50 -0
- package/templates/xbox/tests/windows_platform_test.cpp +75 -3
- package/templates/xbox/third_party/LICENSES.md +14 -0
- package/templates/xbox/third_party/dr_mp3.h +5412 -0
- package/templates/xbox/third_party/dr_wav.h +9131 -0
- package/templates/xbox/third_party/stb_image.h +7988 -0
- package/templates/xbox/third_party/stb_truetype.h +5079 -0
- package/templates/xbox/third_party/stb_vorbis.c +5584 -0
|
@@ -11,11 +11,14 @@
|
|
|
11
11
|
#include "RasterCore.h"
|
|
12
12
|
#include "platform/TextRasterizer.h"
|
|
13
13
|
#include "v8/V8Util.h"
|
|
14
|
+
#include "v8/WeakHandle.h"
|
|
14
15
|
|
|
15
16
|
#include <Windows.h>
|
|
16
17
|
|
|
17
18
|
#include <algorithm>
|
|
19
|
+
#include <cmath>
|
|
18
20
|
#include <cstdio>
|
|
21
|
+
#include <cstdlib>
|
|
19
22
|
#include <cstring>
|
|
20
23
|
#include <memory>
|
|
21
24
|
#include <string>
|
|
@@ -49,6 +52,40 @@ struct State {
|
|
|
49
52
|
// クリップ矩形 (デバイス座標)。TextField はテキスト枠(矩形パス)を clip() で
|
|
50
53
|
// 指定して文字のはみ出しを抑える。
|
|
51
54
|
raster::ClipRect clip;
|
|
55
|
+
|
|
56
|
+
// --- CRC2D の完全な描画状態 (getter/setter で往復可能にする) ---
|
|
57
|
+
// ラスタライズへ実際に反映するもの(textAlign/textBaseline 等)と、
|
|
58
|
+
// 状態として保持するだけのもの(shadow/composite 等の近似)を含む。
|
|
59
|
+
std::string fill_style_str = "#000000";
|
|
60
|
+
std::string stroke_style_str = "#000000";
|
|
61
|
+
std::string line_cap = "butt";
|
|
62
|
+
std::string line_join = "miter";
|
|
63
|
+
double miter_limit = 10.0;
|
|
64
|
+
double line_dash_offset = 0.0;
|
|
65
|
+
std::vector<double> line_dash;
|
|
66
|
+
double shadow_blur = 0.0;
|
|
67
|
+
std::string shadow_color = "rgba(0, 0, 0, 0)";
|
|
68
|
+
double shadow_offset_x = 0.0;
|
|
69
|
+
double shadow_offset_y = 0.0;
|
|
70
|
+
std::string text_align = "start";
|
|
71
|
+
std::string text_baseline = "alphabetic";
|
|
72
|
+
std::string direction = "inherit";
|
|
73
|
+
std::string global_composite_operation = "source-over";
|
|
74
|
+
bool image_smoothing_enabled = true;
|
|
75
|
+
std::string image_smoothing_quality = "low";
|
|
76
|
+
std::string filter = "none";
|
|
77
|
+
std::string font_kerning = "auto";
|
|
78
|
+
std::string letter_spacing = "0px";
|
|
79
|
+
std::string word_spacing = "0px";
|
|
80
|
+
std::string text_rendering = "auto";
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// createLinearGradient / createPattern 等が返す塗りオブジェクトの実体。
|
|
84
|
+
// fillStyle/strokeStyle へ代入された際に代表色 (RepresentativeColor) を取り出す。
|
|
85
|
+
struct PaintObject {
|
|
86
|
+
enum Kind { Gradient, Pattern } kind = Gradient;
|
|
87
|
+
std::vector<std::pair<double, RGBA>> stops; // gradient
|
|
88
|
+
RGBA sample{128,128,128,255}; // pattern の代表色
|
|
52
89
|
};
|
|
53
90
|
|
|
54
91
|
// 2D コンテキストの実体。JS オブジェクトの内部フィールドに保持する。
|
|
@@ -57,6 +94,8 @@ struct Canvas2D {
|
|
|
57
94
|
std::vector<SubPath> path;
|
|
58
95
|
State state;
|
|
59
96
|
std::vector<State> stack;
|
|
97
|
+
// 現在のパス開始点 (arcTo/未サブパス時の moveTo 補完用)
|
|
98
|
+
double cur_x = 0.0, cur_y = 0.0;
|
|
60
99
|
|
|
61
100
|
Canvas2D(int w, int h) : surface(w, h) {}
|
|
62
101
|
};
|
|
@@ -85,6 +124,33 @@ void AddPoint(Canvas2D* c, double x, double y, bool new_sub)
|
|
|
85
124
|
c->path.push_back(SubPath{});
|
|
86
125
|
}
|
|
87
126
|
c->path.back().pts.push_back(p);
|
|
127
|
+
c->cur_x = x; // arcTo 等が参照する現在点 (ユーザー座標)
|
|
128
|
+
c->cur_y = y;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// 値 (色文字列 or gradient/pattern オブジェクト) を代表 RGBA へ解決する。
|
|
132
|
+
RGBA ColorFromValue(v8::Isolate* iso, v8::Local<v8::Value> value)
|
|
133
|
+
{
|
|
134
|
+
if (value->IsObject()) {
|
|
135
|
+
v8::Local<v8::Object> o = value.As<v8::Object>();
|
|
136
|
+
if (o->InternalFieldCount() >= 1) {
|
|
137
|
+
v8::Local<v8::Value> ext = o->GetInternalField(0).As<v8::Value>();
|
|
138
|
+
if (ext->IsExternal()) {
|
|
139
|
+
auto* paint = static_cast<PaintObject*>(ext.As<v8::External>()->Value());
|
|
140
|
+
if (paint) {
|
|
141
|
+
if (paint->kind == PaintObject::Gradient && !paint->stops.empty()) {
|
|
142
|
+
// 代表色 = 全ストップの平均 (近似)。
|
|
143
|
+
uint32_t r=0,g=0,b=0,al=0;
|
|
144
|
+
for (auto& s : paint->stops) { r+=s.second.r; g+=s.second.g; b+=s.second.b; al+=s.second.a; }
|
|
145
|
+
const uint32_t n = static_cast<uint32_t>(paint->stops.size());
|
|
146
|
+
return RGBA{ uint8_t(r/n), uint8_t(g/n), uint8_t(b/n), uint8_t(al/n) };
|
|
147
|
+
}
|
|
148
|
+
return paint->sample;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return ParseColor(ToStdString(iso, value));
|
|
88
154
|
}
|
|
89
155
|
|
|
90
156
|
// --- パス構築 -------------------------------------------------------------
|
|
@@ -159,8 +225,9 @@ void Stroke(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
|
159
225
|
void IsPointInPath(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
160
226
|
{
|
|
161
227
|
Canvas2D* c = Self(a.This());
|
|
162
|
-
a
|
|
163
|
-
|
|
228
|
+
const double px = Arg(a,0), py = Arg(a,1);
|
|
229
|
+
const bool hit = raster::PointInPath(c->path, px, py);
|
|
230
|
+
a.GetReturnValue().Set(v8::Boolean::New(a.GetIsolate(), hit));
|
|
164
231
|
}
|
|
165
232
|
|
|
166
233
|
// --- 変換 ----------------------------------------------------------------
|
|
@@ -201,16 +268,22 @@ void Restore(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
|
201
268
|
Canvas2D* c = Self(a.This());
|
|
202
269
|
if (!c->stack.empty()) { c->state = c->stack.back(); c->stack.pop_back(); }
|
|
203
270
|
}
|
|
204
|
-
// clip():
|
|
205
|
-
//
|
|
206
|
-
//
|
|
271
|
+
// clip(): 現在パスをクリップ領域として設定する (デバイス座標)。既存クリップと積集合。
|
|
272
|
+
// 矩形パス (TextField 枠等) → 外接矩形クリップ (厳密・軽量)
|
|
273
|
+
// 任意形状パス (円/多角形等) → nonzero winding のピクセルマスクで厳密にクリップ
|
|
207
274
|
void Clip(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
208
275
|
{
|
|
209
276
|
Canvas2D* c = Self(a.This());
|
|
210
277
|
double minx, miny, maxx, maxy;
|
|
211
278
|
if (!raster::PathBounds(c->path, &minx, &miny, &maxx, &maxy)) return;
|
|
212
|
-
raster::
|
|
213
|
-
|
|
279
|
+
if (raster::IsAxisAlignedRect(c->path)) {
|
|
280
|
+
// 矩形クリップは外接矩形で厳密 (軽量)。
|
|
281
|
+
raster::IntersectClip(c->state.clip,
|
|
282
|
+
std::floor(minx), std::floor(miny), std::ceil(maxx), std::ceil(maxy));
|
|
283
|
+
} else {
|
|
284
|
+
// 任意形状はピクセルマスクで厳密にクリップする (外接矩形も内部で反映)。
|
|
285
|
+
raster::IntersectClipMask(c->state.clip, c->path, c->surface.width, c->surface.height);
|
|
286
|
+
}
|
|
214
287
|
}
|
|
215
288
|
|
|
216
289
|
// --- 矩形 / クリア --------------------------------------------------------
|
|
@@ -269,8 +342,26 @@ void RasterizeText(Canvas2D* c, const std::wstring& wtext, double x, double y, c
|
|
|
269
342
|
TextBitmap bmp;
|
|
270
343
|
if (!RasterizeTextWithDWrite(c->state.font, wtext, col.r, col.g, col.b, bmp)) return;
|
|
271
344
|
|
|
272
|
-
// fillText の x,y
|
|
273
|
-
Point origin = Apply(c->state.transform, x, y
|
|
345
|
+
// fillText の x,y はベースライン起点。ビットマップは左上起点。
|
|
346
|
+
Point origin = Apply(c->state.transform, x, y);
|
|
347
|
+
// textAlign (device px 近似): start/left=左, center=中央, right/end=右。
|
|
348
|
+
const std::string& al = c->state.text_align;
|
|
349
|
+
if (al == "center") {
|
|
350
|
+
origin.x -= bmp.width / 2.0;
|
|
351
|
+
} else if (al == "right" || al == "end") {
|
|
352
|
+
origin.x -= bmp.width;
|
|
353
|
+
}
|
|
354
|
+
// textBaseline (device px 近似)。
|
|
355
|
+
const std::string& bl = c->state.text_baseline;
|
|
356
|
+
if (bl == "top" || bl == "hanging") {
|
|
357
|
+
// 上端起点: そのまま
|
|
358
|
+
} else if (bl == "middle") {
|
|
359
|
+
origin.y -= bmp.height / 2.0;
|
|
360
|
+
} else if (bl == "bottom" || bl == "ideographic") {
|
|
361
|
+
origin.y -= bmp.height;
|
|
362
|
+
} else {
|
|
363
|
+
origin.y -= bmp.baseline; // alphabetic (既定)
|
|
364
|
+
}
|
|
274
365
|
for (int yy = 0; yy < bmp.height; ++yy) {
|
|
275
366
|
for (int xx = 0; xx < bmp.width; ++xx) {
|
|
276
367
|
const uint8_t* px = &bmp.rgba[(static_cast<size_t>(yy) * bmp.width + xx) * 4];
|
|
@@ -352,47 +443,363 @@ void GetImageData(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
|
352
443
|
a.GetReturnValue().Set(image_data);
|
|
353
444
|
}
|
|
354
445
|
|
|
355
|
-
//
|
|
356
|
-
void
|
|
446
|
+
// --- 追加ジオメトリ: strokeRect / arcTo / ellipse / roundRect ---------------
|
|
447
|
+
void StrokeRect(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
448
|
+
{
|
|
449
|
+
Canvas2D* c = Self(a.This());
|
|
450
|
+
double x = Arg(a,0), y = Arg(a,1), w = Arg(a,2), h = Arg(a,3);
|
|
451
|
+
std::vector<SubPath> tmp; tmp.push_back(SubPath{});
|
|
452
|
+
const double cn[4][2] = { {x,y}, {x+w,y}, {x+w,y+h}, {x,y+h} };
|
|
453
|
+
for (auto& pt : cn) tmp.back().pts.push_back(Apply(c->state.transform, pt[0], pt[1]));
|
|
454
|
+
tmp.back().closed = true;
|
|
455
|
+
raster::StrokePath(c->surface, c->state.clip, tmp, c->state.stroke, c->state.global_alpha);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
void ArcTo(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
459
|
+
{
|
|
460
|
+
Canvas2D* c = Self(a.This());
|
|
461
|
+
const double x1 = Arg(a,0), y1 = Arg(a,1), x2 = Arg(a,2), y2 = Arg(a,3), r = Arg(a,4);
|
|
462
|
+
const double x0 = c->cur_x, y0 = c->cur_y;
|
|
463
|
+
const double a1 = x0-x1, b1 = y0-y1, a2 = x2-x1, b2 = y2-y1;
|
|
464
|
+
const double l1 = std::hypot(a1,b1), l2 = std::hypot(a2,b2);
|
|
465
|
+
if (l1 < 1e-6 || l2 < 1e-6 || r < 1e-6) { AddPoint(c, x1, y1, c->path.empty()); return; }
|
|
466
|
+
double cosang = std::clamp((a1*a2 + b1*b2) / (l1*l2), -1.0, 1.0);
|
|
467
|
+
const double ang = std::acos(cosang);
|
|
468
|
+
const double th = std::tan(ang / 2);
|
|
469
|
+
if (th < 1e-6) { AddPoint(c, x1, y1, c->path.empty()); return; }
|
|
470
|
+
const double dist = r / th;
|
|
471
|
+
const double t1x = x1 + a1/l1*dist, t1y = y1 + b1/l1*dist;
|
|
472
|
+
const double t2x = x1 + a2/l2*dist, t2y = y1 + b2/l2*dist;
|
|
473
|
+
AddPoint(c, t1x, t1y, c->path.empty()); // 現在点→第一接点
|
|
474
|
+
double bx = a1/l1 + a2/l2, by = b1/l1 + b2/l2;
|
|
475
|
+
const double bl = std::hypot(bx, by);
|
|
476
|
+
if (bl > 1e-6) {
|
|
477
|
+
const double cenDist = r / std::sin(ang / 2);
|
|
478
|
+
const double cx = x1 + bx/bl*cenDist, cy = y1 + by/bl*cenDist;
|
|
479
|
+
const double sa = std::atan2(t1y-cy, t1x-cx), ea = std::atan2(t2y-cy, t2x-cx);
|
|
480
|
+
const bool ccw = (a1*b2 - b1*a2) > 0;
|
|
481
|
+
raster::FlattenArc(c->path.back().pts, c->state.transform, cx, cy, r, sa, ea, ccw);
|
|
482
|
+
}
|
|
483
|
+
c->cur_x = t2x; c->cur_y = t2y;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
void Ellipse(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
487
|
+
{
|
|
488
|
+
Canvas2D* c = Self(a.This());
|
|
489
|
+
const double cx = Arg(a,0), cy = Arg(a,1), rx = Arg(a,2), ry = Arg(a,3), rot = Arg(a,4);
|
|
490
|
+
double s = Arg(a,5), e = Arg(a,6, 2*raster::kPi);
|
|
491
|
+
const bool ccw = a.Length() > 7 && a[7]->BooleanValue(a.GetIsolate());
|
|
492
|
+
if (ccw && e > s) e -= 2*raster::kPi;
|
|
493
|
+
if (!ccw && e < s) e += 2*raster::kPi;
|
|
494
|
+
if (c->path.empty()) c->path.push_back(SubPath{});
|
|
495
|
+
const double cr = std::cos(rot), sr = std::sin(rot);
|
|
496
|
+
const int steps = 48;
|
|
497
|
+
for (int i = 0; i <= steps; ++i) {
|
|
498
|
+
const double t = s + (e - s) * (static_cast<double>(i) / steps);
|
|
499
|
+
const double ex = rx*std::cos(t), ey = ry*std::sin(t);
|
|
500
|
+
c->path.back().pts.push_back(
|
|
501
|
+
Apply(c->state.transform, cx + ex*cr - ey*sr, cy + ex*sr + ey*cr));
|
|
502
|
+
}
|
|
503
|
+
}
|
|
357
504
|
|
|
358
|
-
|
|
505
|
+
void RoundRect(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
506
|
+
{
|
|
507
|
+
Canvas2D* c = Self(a.This());
|
|
508
|
+
const double x = Arg(a,0), y = Arg(a,1), w = Arg(a,2), h = Arg(a,3);
|
|
509
|
+
double r = 0.0;
|
|
510
|
+
if (a.Length() > 4) {
|
|
511
|
+
if (a[4]->IsNumber()) {
|
|
512
|
+
r = a[4].As<v8::Number>()->Value();
|
|
513
|
+
} else if (a[4]->IsArray()) {
|
|
514
|
+
auto arr = a[4].As<v8::Array>();
|
|
515
|
+
v8::Local<v8::Value> v0;
|
|
516
|
+
if (arr->Length() > 0 && arr->Get(a.GetIsolate()->GetCurrentContext(), 0).ToLocal(&v0) && v0->IsNumber()) {
|
|
517
|
+
r = v0.As<v8::Number>()->Value();
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
r = std::min(r, std::min(std::abs(w), std::abs(h)) / 2.0);
|
|
522
|
+
c->path.push_back(SubPath{});
|
|
523
|
+
auto& pts = c->path.back().pts;
|
|
524
|
+
const double hp = raster::kPi / 2;
|
|
525
|
+
raster::FlattenArc(pts, c->state.transform, x+w-r, y+r, r, -hp, 0.0, false); // 右上
|
|
526
|
+
raster::FlattenArc(pts, c->state.transform, x+w-r, y+h-r, r, 0.0, hp, false); // 右下
|
|
527
|
+
raster::FlattenArc(pts, c->state.transform, x+r, y+h-r, r, hp, raster::kPi, false); // 左下
|
|
528
|
+
raster::FlattenArc(pts, c->state.transform, x+r, y+r, r, raster::kPi, hp*3, false); // 左上
|
|
529
|
+
c->path.back().closed = true;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// --- 追加変換: resetTransform / getTransform --------------------------------
|
|
533
|
+
void ResetTransform(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
534
|
+
{
|
|
535
|
+
Self(a.This())->state.transform = Mat{1,0,0,1,0,0};
|
|
536
|
+
}
|
|
537
|
+
void GetTransform(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
538
|
+
{
|
|
539
|
+
v8::Isolate* iso = a.GetIsolate();
|
|
540
|
+
const Mat& m = Self(a.This())->state.transform;
|
|
541
|
+
v8::Local<v8::Object> o = v8::Object::New(iso);
|
|
542
|
+
SetValue(iso, o, "a", v8::Number::New(iso, m.a));
|
|
543
|
+
SetValue(iso, o, "b", v8::Number::New(iso, m.b));
|
|
544
|
+
SetValue(iso, o, "c", v8::Number::New(iso, m.c));
|
|
545
|
+
SetValue(iso, o, "d", v8::Number::New(iso, m.d));
|
|
546
|
+
SetValue(iso, o, "e", v8::Number::New(iso, m.e));
|
|
547
|
+
SetValue(iso, o, "f", v8::Number::New(iso, m.f));
|
|
548
|
+
// DOMMatrix 互換の別名も付ける
|
|
549
|
+
SetValue(iso, o, "m11", v8::Number::New(iso, m.a));
|
|
550
|
+
SetValue(iso, o, "m12", v8::Number::New(iso, m.b));
|
|
551
|
+
SetValue(iso, o, "m21", v8::Number::New(iso, m.c));
|
|
552
|
+
SetValue(iso, o, "m22", v8::Number::New(iso, m.d));
|
|
553
|
+
SetValue(iso, o, "m41", v8::Number::New(iso, m.e));
|
|
554
|
+
SetValue(iso, o, "m42", v8::Number::New(iso, m.f));
|
|
555
|
+
a.GetReturnValue().Set(o);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// --- 追加ライン: getLineDash / isPointInStroke -----------------------------
|
|
559
|
+
void GetLineDash(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
560
|
+
{
|
|
561
|
+
v8::Isolate* iso = a.GetIsolate();
|
|
562
|
+
v8::Local<v8::Context> ctx = iso->GetCurrentContext();
|
|
563
|
+
const auto& dash = Self(a.This())->state.line_dash;
|
|
564
|
+
v8::Local<v8::Array> arr = v8::Array::New(iso, static_cast<int>(dash.size()));
|
|
565
|
+
for (uint32_t i = 0; i < dash.size(); ++i) {
|
|
566
|
+
arr->Set(ctx, i, v8::Number::New(iso, dash[i])).Check();
|
|
567
|
+
}
|
|
568
|
+
a.GetReturnValue().Set(arr);
|
|
569
|
+
}
|
|
570
|
+
// isPointInStroke: 近似としてパス内包 (fill) と同じ判定を返す。
|
|
571
|
+
void IsPointInStroke(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
572
|
+
{
|
|
573
|
+
Canvas2D* c = Self(a.This());
|
|
574
|
+
a.GetReturnValue().Set(v8::Boolean::New(
|
|
575
|
+
a.GetIsolate(), raster::PointInPath(c->path, Arg(a,0), Arg(a,1))));
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// --- 追加: gradient / pattern ----------------------------------------------
|
|
579
|
+
void AddColorStop(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
580
|
+
{
|
|
581
|
+
v8::Local<v8::Object> self = a.This();
|
|
582
|
+
if (self->InternalFieldCount() < 1) return;
|
|
583
|
+
v8::Local<v8::Value> ext = self->GetInternalField(0).As<v8::Value>();
|
|
584
|
+
if (!ext->IsExternal()) return;
|
|
585
|
+
auto* p = static_cast<PaintObject*>(ext.As<v8::External>()->Value());
|
|
586
|
+
if (!p) return;
|
|
587
|
+
p->stops.push_back({ Arg(a,0), ParseColor(ToStdString(a.GetIsolate(), a.Length()>1 ? a[1] : v8::Local<v8::Value>())) });
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
v8::Local<v8::Object> MakePaintObject(v8::Isolate* isolate, PaintObject* paint)
|
|
591
|
+
{
|
|
592
|
+
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
|
|
593
|
+
v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
|
|
594
|
+
tmpl->SetInternalFieldCount(1);
|
|
595
|
+
v8::Local<v8::Object> o = tmpl->NewInstance(ctx).ToLocalChecked();
|
|
596
|
+
o->SetInternalField(0, v8::External::New(isolate, paint));
|
|
597
|
+
v8util::AttachWeak(isolate, o, paint);
|
|
598
|
+
SetMethod(isolate, o, "addColorStop", AddColorStop);
|
|
599
|
+
return o;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
void CreateLinearGradient(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
603
|
+
{
|
|
604
|
+
auto* p = new PaintObject();
|
|
605
|
+
p->kind = PaintObject::Gradient;
|
|
606
|
+
a.GetReturnValue().Set(MakePaintObject(a.GetIsolate(), p));
|
|
607
|
+
}
|
|
608
|
+
void CreateRadialGradient(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
609
|
+
{
|
|
610
|
+
auto* p = new PaintObject();
|
|
611
|
+
p->kind = PaintObject::Gradient;
|
|
612
|
+
a.GetReturnValue().Set(MakePaintObject(a.GetIsolate(), p));
|
|
613
|
+
}
|
|
614
|
+
void CreateConicGradient(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
615
|
+
{
|
|
616
|
+
auto* p = new PaintObject();
|
|
617
|
+
p->kind = PaintObject::Gradient;
|
|
618
|
+
a.GetReturnValue().Set(MakePaintObject(a.GetIsolate(), p));
|
|
619
|
+
}
|
|
620
|
+
void CreatePattern(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
621
|
+
{
|
|
622
|
+
v8::Isolate* iso = a.GetIsolate();
|
|
623
|
+
auto* p = new PaintObject();
|
|
624
|
+
p->kind = PaintObject::Pattern;
|
|
625
|
+
// 画像の代表色 (中央付近の平均) をサンプルする。
|
|
626
|
+
const uint8_t* src = nullptr; uint32_t sw = 0, sh = 0;
|
|
627
|
+
if (a.Length() > 0 && GetImageSourcePixels(iso, a[0], &src, &sw, &sh) && src && sw && sh) {
|
|
628
|
+
uint64_t r=0,g=0,b=0,al=0,n=0;
|
|
629
|
+
for (uint32_t yy = 0; yy < sh; yy += std::max(1u, sh/16)) {
|
|
630
|
+
for (uint32_t xx = 0; xx < sw; xx += std::max(1u, sw/16)) {
|
|
631
|
+
const uint8_t* px = &src[(static_cast<size_t>(yy)*sw + xx)*4];
|
|
632
|
+
r+=px[0]; g+=px[1]; b+=px[2]; al+=px[3]; ++n;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
if (n) p->sample = RGBA{ uint8_t(r/n), uint8_t(g/n), uint8_t(b/n), uint8_t(al/n) };
|
|
636
|
+
}
|
|
637
|
+
a.GetReturnValue().Set(MakePaintObject(iso, p));
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// --- 追加: ImageData 生成 / 書き戻し ---------------------------------------
|
|
641
|
+
void CreateImageData(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
642
|
+
{
|
|
643
|
+
v8::Isolate* iso = a.GetIsolate();
|
|
644
|
+
v8::Local<v8::Context> ctx = iso->GetCurrentContext();
|
|
645
|
+
int w = 0, h = 0;
|
|
646
|
+
if (a.Length() > 0 && a[0]->IsObject() && !a[0]->IsNumber()) {
|
|
647
|
+
// createImageData(imagedata): 同サイズの空データ
|
|
648
|
+
v8::Local<v8::Object> o = a[0].As<v8::Object>();
|
|
649
|
+
v8::Local<v8::Value> wv, hv;
|
|
650
|
+
if (o->Get(ctx, Str(iso, "width")).ToLocal(&wv)) w = static_cast<int>(wv->NumberValue(ctx).FromMaybe(0));
|
|
651
|
+
if (o->Get(ctx, Str(iso, "height")).ToLocal(&hv)) h = static_cast<int>(hv->NumberValue(ctx).FromMaybe(0));
|
|
652
|
+
} else {
|
|
653
|
+
w = std::abs(static_cast<int>(Arg(a,0)));
|
|
654
|
+
h = std::abs(static_cast<int>(Arg(a,1)));
|
|
655
|
+
}
|
|
656
|
+
if (w <= 0) w = 1;
|
|
657
|
+
if (h <= 0) h = 1;
|
|
658
|
+
const size_t bytes = static_cast<size_t>(w) * h * 4;
|
|
659
|
+
auto store = v8::ArrayBuffer::NewBackingStore(iso, bytes); // 0 初期化
|
|
660
|
+
auto ab = v8::ArrayBuffer::New(iso, std::move(store));
|
|
661
|
+
auto arr = v8::Uint8ClampedArray::New(ab, 0, bytes);
|
|
662
|
+
v8::Local<v8::Object> image_data = v8::Object::New(iso);
|
|
663
|
+
SetValue(iso, image_data, "width", v8::Integer::New(iso, w));
|
|
664
|
+
SetValue(iso, image_data, "height", v8::Integer::New(iso, h));
|
|
665
|
+
image_data->Set(ctx, Str(iso, "data"), arr).Check();
|
|
666
|
+
a.GetReturnValue().Set(image_data);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
void PutImageData(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
670
|
+
{
|
|
671
|
+
v8::Isolate* iso = a.GetIsolate();
|
|
672
|
+
v8::Local<v8::Context> ctx = iso->GetCurrentContext();
|
|
673
|
+
Canvas2D* c = Self(a.This());
|
|
674
|
+
if (a.Length() < 3 || !a[0]->IsObject()) return;
|
|
675
|
+
v8::Local<v8::Object> o = a[0].As<v8::Object>();
|
|
676
|
+
v8::Local<v8::Value> wv, hv, dv;
|
|
677
|
+
if (!o->Get(ctx, Str(iso, "width")).ToLocal(&wv) ||
|
|
678
|
+
!o->Get(ctx, Str(iso, "height")).ToLocal(&hv) ||
|
|
679
|
+
!o->Get(ctx, Str(iso, "data")).ToLocal(&dv) || !dv->IsTypedArray()) {
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
const int iw = static_cast<int>(wv->NumberValue(ctx).FromMaybe(0));
|
|
683
|
+
const int ih = static_cast<int>(hv->NumberValue(ctx).FromMaybe(0));
|
|
684
|
+
auto ta = dv.As<v8::TypedArray>();
|
|
685
|
+
auto ab = ta->Buffer();
|
|
686
|
+
const uint8_t* data = static_cast<const uint8_t*>(ab->Data()) + ta->ByteOffset();
|
|
687
|
+
const int dx = static_cast<int>(Arg(a,1)), dy = static_cast<int>(Arg(a,2));
|
|
688
|
+
// putImageData は変換・クリップ非適用でそのまま書き込む (Canvas 仕様)。
|
|
689
|
+
for (int yy = 0; yy < ih; ++yy) {
|
|
690
|
+
for (int xx = 0; xx < iw; ++xx) {
|
|
691
|
+
const int sx = dx + xx, sy = dy + yy;
|
|
692
|
+
if (sx < 0 || sy < 0 || sx >= c->surface.width || sy >= c->surface.height) continue;
|
|
693
|
+
const size_t si = (static_cast<size_t>(yy)*iw + xx) * 4;
|
|
694
|
+
const size_t di = (static_cast<size_t>(sy)*c->surface.width + sx) * 4;
|
|
695
|
+
std::memcpy(&c->surface.pixels[di], &data[si], 4);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// --- 追加: reset() ----------------------------------------------------------
|
|
701
|
+
void Reset(const v8::FunctionCallbackInfo<v8::Value>& a)
|
|
702
|
+
{
|
|
703
|
+
Canvas2D* c = Self(a.This());
|
|
704
|
+
c->path.clear();
|
|
705
|
+
c->stack.clear();
|
|
706
|
+
c->state = State{};
|
|
707
|
+
std::fill(c->surface.pixels.begin(), c->surface.pixels.end(), static_cast<uint8_t>(0));
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// CanvasRenderingContext2D の全プロパティを getter/setter 付きで設置する。
|
|
711
|
+
// 解釈して描画へ反映するもの(fill/stroke/font/textAlign/textBaseline/lineWidth/
|
|
712
|
+
// globalAlpha)と、状態として往復保持するだけのもの(shadow/composite/filter 等の
|
|
713
|
+
// 近似)を含む。全て state に持たせるため save()/restore() でも復元される。
|
|
359
714
|
void InstallAccessors(v8::Isolate* isolate, v8::Local<v8::Object> obj)
|
|
360
715
|
{
|
|
361
716
|
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
717
|
+
|
|
718
|
+
// state の string/number/bool メンバへ往復するアクセサを設置するマクロ。
|
|
719
|
+
#define N2D_STR_PROP(NAME, MEMBER) \
|
|
720
|
+
obj->SetNativeDataProperty(ctx, Str(isolate, NAME), \
|
|
721
|
+
[](v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info){ \
|
|
722
|
+
info.GetReturnValue().Set(v8util::Str(info.GetIsolate(), Self(info.This())->state.MEMBER)); }, \
|
|
723
|
+
[](v8::Local<v8::Name>, v8::Local<v8::Value> v, const v8::PropertyCallbackInfo<void>& info){ \
|
|
724
|
+
Self(info.This())->state.MEMBER = ToStdString(info.GetIsolate(), v); }).Check()
|
|
725
|
+
#define N2D_NUM_PROP(NAME, MEMBER) \
|
|
726
|
+
obj->SetNativeDataProperty(ctx, Str(isolate, NAME), \
|
|
727
|
+
[](v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info){ \
|
|
728
|
+
info.GetReturnValue().Set(v8::Number::New(info.GetIsolate(), Self(info.This())->state.MEMBER)); }, \
|
|
729
|
+
[](v8::Local<v8::Name>, v8::Local<v8::Value> v, const v8::PropertyCallbackInfo<void>& info){ \
|
|
730
|
+
if (v->IsNumber()) Self(info.This())->state.MEMBER = v.As<v8::Number>()->Value(); }).Check()
|
|
731
|
+
#define N2D_BOOL_PROP(NAME, MEMBER) \
|
|
732
|
+
obj->SetNativeDataProperty(ctx, Str(isolate, NAME), \
|
|
733
|
+
[](v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info){ \
|
|
734
|
+
info.GetReturnValue().Set(v8::Boolean::New(info.GetIsolate(), Self(info.This())->state.MEMBER)); }, \
|
|
735
|
+
[](v8::Local<v8::Name>, v8::Local<v8::Value> v, const v8::PropertyCallbackInfo<void>& info){ \
|
|
736
|
+
Self(info.This())->state.MEMBER = v->BooleanValue(info.GetIsolate()); }).Check()
|
|
737
|
+
|
|
738
|
+
// fillStyle / strokeStyle: gradient/pattern オブジェクトも受け取り代表色へ解決。
|
|
739
|
+
// 重要: getter は「代入した色を #rrggbb に正規化して」返す (ブラウザ準拠)。
|
|
740
|
+
// player は色文字列の数値化に読み戻しを使う (@next2d/filters の
|
|
741
|
+
// $convertColorStringToNumber は `+("0x"+ctx.fillStyle.slice(1))` で解釈するため、
|
|
742
|
+
// getter が "rgb(191,255,255)" 等の生文字列を返すと NaN になり、その色を使う
|
|
743
|
+
// グラデーション (スライム body 等) が黒くなる)。パース済み RGBA を hex 化して保持する。
|
|
375
744
|
obj->SetNativeDataProperty(ctx, Str(isolate, "fillStyle"),
|
|
376
745
|
[](v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
377
|
-
|
|
378
|
-
char buf[8];
|
|
379
|
-
std::snprintf(buf, sizeof(buf), "#%02x%02x%02x", c.r, c.g, c.b);
|
|
380
|
-
info.GetReturnValue().Set(v8util::Str(info.GetIsolate(), buf));
|
|
746
|
+
info.GetReturnValue().Set(v8util::Str(info.GetIsolate(), Self(info.This())->state.fill_style_str));
|
|
381
747
|
},
|
|
382
748
|
[](v8::Local<v8::Name>, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
749
|
+
Canvas2D* c = Self(info.This());
|
|
750
|
+
c->state.fill = ColorFromValue(info.GetIsolate(), value);
|
|
751
|
+
if (value->IsString()) {
|
|
752
|
+
char hex[8];
|
|
753
|
+
std::snprintf(hex, sizeof(hex), "#%02x%02x%02x",
|
|
754
|
+
static_cast<unsigned>(c->state.fill.r),
|
|
755
|
+
static_cast<unsigned>(c->state.fill.g),
|
|
756
|
+
static_cast<unsigned>(c->state.fill.b));
|
|
757
|
+
c->state.fill_style_str = hex;
|
|
758
|
+
}
|
|
391
759
|
}).Check();
|
|
392
|
-
obj->SetNativeDataProperty(ctx, Str(isolate, "
|
|
393
|
-
[](v8::Local<v8::Name>, v8::
|
|
394
|
-
|
|
760
|
+
obj->SetNativeDataProperty(ctx, Str(isolate, "strokeStyle"),
|
|
761
|
+
[](v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
762
|
+
info.GetReturnValue().Set(v8util::Str(info.GetIsolate(), Self(info.This())->state.stroke_style_str));
|
|
763
|
+
},
|
|
764
|
+
[](v8::Local<v8::Name>, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) {
|
|
765
|
+
Canvas2D* c = Self(info.This());
|
|
766
|
+
c->state.stroke = ColorFromValue(info.GetIsolate(), value);
|
|
767
|
+
if (value->IsString()) {
|
|
768
|
+
char hex[8];
|
|
769
|
+
std::snprintf(hex, sizeof(hex), "#%02x%02x%02x",
|
|
770
|
+
static_cast<unsigned>(c->state.stroke.r),
|
|
771
|
+
static_cast<unsigned>(c->state.stroke.g),
|
|
772
|
+
static_cast<unsigned>(c->state.stroke.b));
|
|
773
|
+
c->state.stroke_style_str = hex;
|
|
774
|
+
}
|
|
395
775
|
}).Check();
|
|
776
|
+
|
|
777
|
+
N2D_STR_PROP("font", font);
|
|
778
|
+
N2D_NUM_PROP("lineWidth", line_width);
|
|
779
|
+
N2D_NUM_PROP("globalAlpha", global_alpha);
|
|
780
|
+
N2D_STR_PROP("lineCap", line_cap);
|
|
781
|
+
N2D_STR_PROP("lineJoin", line_join);
|
|
782
|
+
N2D_NUM_PROP("miterLimit", miter_limit);
|
|
783
|
+
N2D_NUM_PROP("lineDashOffset", line_dash_offset);
|
|
784
|
+
N2D_NUM_PROP("shadowBlur", shadow_blur);
|
|
785
|
+
N2D_STR_PROP("shadowColor", shadow_color);
|
|
786
|
+
N2D_NUM_PROP("shadowOffsetX", shadow_offset_x);
|
|
787
|
+
N2D_NUM_PROP("shadowOffsetY", shadow_offset_y);
|
|
788
|
+
N2D_STR_PROP("textAlign", text_align);
|
|
789
|
+
N2D_STR_PROP("textBaseline", text_baseline);
|
|
790
|
+
N2D_STR_PROP("direction", direction);
|
|
791
|
+
N2D_STR_PROP("globalCompositeOperation", global_composite_operation);
|
|
792
|
+
N2D_BOOL_PROP("imageSmoothingEnabled", image_smoothing_enabled);
|
|
793
|
+
N2D_STR_PROP("imageSmoothingQuality", image_smoothing_quality);
|
|
794
|
+
N2D_STR_PROP("filter", filter);
|
|
795
|
+
N2D_STR_PROP("fontKerning", font_kerning);
|
|
796
|
+
N2D_STR_PROP("letterSpacing", letter_spacing);
|
|
797
|
+
N2D_STR_PROP("wordSpacing", word_spacing);
|
|
798
|
+
N2D_STR_PROP("textRendering", text_rendering);
|
|
799
|
+
|
|
800
|
+
#undef N2D_STR_PROP
|
|
801
|
+
#undef N2D_NUM_PROP
|
|
802
|
+
#undef N2D_BOOL_PROP
|
|
396
803
|
}
|
|
397
804
|
|
|
398
805
|
} // namespace
|
|
@@ -424,9 +831,9 @@ v8::Local<v8::Object> CreateCanvas2DContext(v8::Isolate* isolate, HostContext* /
|
|
|
424
831
|
|
|
425
832
|
auto* impl = new Canvas2D(width > 0 ? width : 1, height > 0 ? height : 1);
|
|
426
833
|
obj->SetInternalField(0, v8::External::New(isolate, impl));
|
|
427
|
-
|
|
428
|
-
handle->SetWeak(impl, ReleaseCanvas2D, v8::WeakCallbackType::kParameter);
|
|
834
|
+
v8util::AttachWeak(isolate, obj, impl);
|
|
429
835
|
|
|
836
|
+
// パス構築
|
|
430
837
|
SetMethod(isolate, obj, "beginPath", BeginPath);
|
|
431
838
|
SetMethod(isolate, obj, "moveTo", MoveTo);
|
|
432
839
|
SetMethod(isolate, obj, "lineTo", LineTo);
|
|
@@ -434,26 +841,72 @@ v8::Local<v8::Object> CreateCanvas2DContext(v8::Isolate* isolate, HostContext* /
|
|
|
434
841
|
SetMethod(isolate, obj, "bezierCurveTo", BezierCurveTo);
|
|
435
842
|
SetMethod(isolate, obj, "quadraticCurveTo", QuadraticCurveTo);
|
|
436
843
|
SetMethod(isolate, obj, "arc", Arc);
|
|
844
|
+
SetMethod(isolate, obj, "arcTo", ArcTo);
|
|
845
|
+
SetMethod(isolate, obj, "ellipse", Ellipse);
|
|
437
846
|
SetMethod(isolate, obj, "rect", Rect);
|
|
847
|
+
SetMethod(isolate, obj, "roundRect", RoundRect);
|
|
848
|
+
// 塗り/線/判定
|
|
438
849
|
SetMethod(isolate, obj, "fill", Fill);
|
|
439
850
|
SetMethod(isolate, obj, "stroke", Stroke);
|
|
440
851
|
SetMethod(isolate, obj, "clip", Clip);
|
|
441
852
|
SetMethod(isolate, obj, "isPointInPath", IsPointInPath);
|
|
853
|
+
SetMethod(isolate, obj, "isPointInStroke", IsPointInStroke);
|
|
854
|
+
// 変換
|
|
442
855
|
SetMethod(isolate, obj, "setTransform", SetTransform);
|
|
443
856
|
SetMethod(isolate, obj, "transform", Transform);
|
|
444
857
|
SetMethod(isolate, obj, "translate", Translate);
|
|
445
858
|
SetMethod(isolate, obj, "scale", Scale);
|
|
446
859
|
SetMethod(isolate, obj, "rotate", Rotate);
|
|
860
|
+
SetMethod(isolate, obj, "resetTransform", ResetTransform);
|
|
861
|
+
SetMethod(isolate, obj, "getTransform", GetTransform);
|
|
862
|
+
// 状態スタック
|
|
447
863
|
SetMethod(isolate, obj, "save", Save);
|
|
448
864
|
SetMethod(isolate, obj, "restore", Restore);
|
|
865
|
+
SetMethod(isolate, obj, "reset", Reset);
|
|
866
|
+
// 矩形
|
|
449
867
|
SetMethod(isolate, obj, "clearRect", ClearRect);
|
|
450
868
|
SetMethod(isolate, obj, "fillRect", FillRect);
|
|
869
|
+
SetMethod(isolate, obj, "strokeRect", StrokeRect);
|
|
870
|
+
// テキスト
|
|
451
871
|
SetMethod(isolate, obj, "measureText", MeasureText);
|
|
452
872
|
SetMethod(isolate, obj, "fillText", FillText);
|
|
453
873
|
SetMethod(isolate, obj, "strokeText", StrokeText);
|
|
874
|
+
// 画像 / ImageData
|
|
454
875
|
SetMethod(isolate, obj, "drawImage", DrawImage);
|
|
455
876
|
SetMethod(isolate, obj, "getImageData", GetImageData);
|
|
456
|
-
SetMethod(isolate, obj, "
|
|
877
|
+
SetMethod(isolate, obj, "createImageData", CreateImageData);
|
|
878
|
+
SetMethod(isolate, obj, "putImageData", PutImageData);
|
|
879
|
+
// gradient / pattern
|
|
880
|
+
SetMethod(isolate, obj, "createLinearGradient", CreateLinearGradient);
|
|
881
|
+
SetMethod(isolate, obj, "createRadialGradient", CreateRadialGradient);
|
|
882
|
+
SetMethod(isolate, obj, "createConicGradient", CreateConicGradient);
|
|
883
|
+
SetMethod(isolate, obj, "createPattern", CreatePattern);
|
|
884
|
+
// 線種
|
|
885
|
+
SetMethod(isolate, obj, "getLineDash", GetLineDash);
|
|
886
|
+
SetMethod(isolate, obj, "setLineDash", [](const v8::FunctionCallbackInfo<v8::Value>& a) {
|
|
887
|
+
Canvas2D* c = Self(a.This());
|
|
888
|
+
c->state.line_dash.clear();
|
|
889
|
+
if (a.Length() > 0 && a[0]->IsArray()) {
|
|
890
|
+
auto arr = a[0].As<v8::Array>();
|
|
891
|
+
v8::Local<v8::Context> ctx2 = a.GetIsolate()->GetCurrentContext();
|
|
892
|
+
for (uint32_t i = 0; i < arr->Length(); ++i) {
|
|
893
|
+
v8::Local<v8::Value> v;
|
|
894
|
+
if (arr->Get(ctx2, i).ToLocal(&v) && v->IsNumber()) {
|
|
895
|
+
c->state.line_dash.push_back(v.As<v8::Number>()->Value());
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
});
|
|
900
|
+
// 参考: getContextAttributes (最小)
|
|
901
|
+
SetMethod(isolate, obj, "getContextAttributes", [](const v8::FunctionCallbackInfo<v8::Value>& a) {
|
|
902
|
+
v8::Isolate* iso = a.GetIsolate();
|
|
903
|
+
v8::Local<v8::Object> o = v8::Object::New(iso);
|
|
904
|
+
SetValue(iso, o, "alpha", v8::Boolean::New(iso, true));
|
|
905
|
+
SetValue(iso, o, "desynchronized", v8::Boolean::New(iso, false));
|
|
906
|
+
SetValue(iso, o, "colorSpace", v8util::Str(iso, "srgb"));
|
|
907
|
+
SetValue(iso, o, "willReadFrequently", v8::Boolean::New(iso, false));
|
|
908
|
+
a.GetReturnValue().Set(o);
|
|
909
|
+
});
|
|
457
910
|
|
|
458
911
|
InstallAccessors(isolate, obj);
|
|
459
912
|
return obj;
|
|
@@ -30,7 +30,12 @@ void Log(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
|
30
30
|
|
|
31
31
|
void Error(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
32
32
|
{
|
|
33
|
-
|
|
33
|
+
// console.error / console.warn は GUI 実行では stderr が見えないため、
|
|
34
|
+
// next2d-error.log にもミラーする (player 側のエラー・警告や WebGPU の
|
|
35
|
+
// error scope 結果などを掴む)。
|
|
36
|
+
const std::string msg = FormatArgs(args.GetIsolate(), args);
|
|
37
|
+
std::cerr << msg << std::endl;
|
|
38
|
+
v8util::AppendErrorLog("[console] " + msg);
|
|
34
39
|
}
|
|
35
40
|
|
|
36
41
|
} // namespace
|