1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_canvas_bridge.h"
17
18 #include "base/utils/linear_map.h"
19 #include "base/utils/string_utils.h"
20
21 #include "core/components/custom_paint/offscreen_canvas.h"
22 #include "frameworks/bridge/js_frontend/engine/common/js_engine.h"
23 #include "frameworks/bridge/js_frontend/engine/jsi/ark_js_value.h"
24 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_offscreen_canvas_bridge.h"
25
26 #ifdef PIXEL_MAP_SUPPORTED
27 #include "pixel_map.h"
28 #include "pixel_map_napi.h"
29 #endif
30
31 namespace OHOS::Ace::Framework {
32 namespace {
33
34 constexpr char CANVAS_TYPE_WEBGL[] = "webgl";
35 constexpr char CANVAS_TYPE_WEBGL2[] = "webgl2";
36 constexpr char CANVAS_WEBGL_SO[] = "webglnapi";
37
38 #if !defined(PREVIEW)
CreatePixelMapFromNapiValue(const shared_ptr<JsRuntime> & runtime,shared_ptr<JsValue> jsValue)39 RefPtr<PixelMap> CreatePixelMapFromNapiValue(const shared_ptr<JsRuntime>& runtime, shared_ptr<JsValue> jsValue)
40 {
41 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
42 if (!engine) {
43 LOGE(" engine is null.");
44 return nullptr;
45 }
46
47 auto nativeEngine = static_cast<ArkNativeEngine*>(engine->GetNativeEngine());
48 if (!nativeEngine) {
49 LOGE("NativeEngine is null");
50 return nullptr;
51 }
52
53 shared_ptr<ArkJSValue> arkJsValue = std::static_pointer_cast<ArkJSValue>(jsValue);
54 if (!arkJsValue) {
55 LOGE("arkJsValue is null.");
56 return nullptr;
57 }
58 shared_ptr<ArkJSRuntime> arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
59 if (!arkRuntime) {
60 LOGE("arkRuntime is null");
61 return nullptr;
62 }
63
64 JSValueWrapper valueWrapper = arkJsValue->GetValue(arkRuntime);
65 napi_value napiValue = nativeEngine->ValueToNapiValue(valueWrapper);
66
67 PixelMapNapiEntry pixelMapNapiEntry = JsEngine::GetPixelMapNapiEntry();
68 if (!pixelMapNapiEntry) {
69 LOGE("pixelMapNapiEntry is null");
70 return nullptr;
71 }
72 void* pixmapPtrAddr = pixelMapNapiEntry(
73 reinterpret_cast<napi_env>(nativeEngine), napiValue);
74 if (pixmapPtrAddr == nullptr) {
75 LOGE(" Failed to get pixmap pointer");
76 return nullptr;
77 }
78 return PixelMap::CreatePixelMap(pixmapPtrAddr);
79 }
80 #endif
81
82 template<typename T>
ConvertStrToEnum(const char * key,const LinearMapNode<T> * map,size_t length,T defaultValue)83 inline T ConvertStrToEnum(const char* key, const LinearMapNode<T>* map, size_t length, T defaultValue)
84 {
85 int64_t index = BinarySearchFindIndex(map, length, key);
86 return index != -1 ? map[index].value : defaultValue;
87 }
88
89 const LinearMapNode<TextBaseline> BASELINE_TABLE[] = {
90 { "alphabetic", TextBaseline::ALPHABETIC },
91 { "bottom", TextBaseline::BOTTOM },
92 { "hanging", TextBaseline::HANGING },
93 { "ideographic", TextBaseline::IDEOGRAPHIC },
94 { "middle", TextBaseline::MIDDLE },
95 { "top", TextBaseline::TOP },
96 };
97
98 const std::set<std::string> FONT_WEIGHTS = { "normal", "bold", "lighter", "bolder",
99 "100", "200", "300", "400", "500", "600", "700", "800", "900" };
100 const std::set<std::string> FONT_STYLES = { "italic", "oblique", "normal" };
101 const std::set<std::string> FONT_FAMILIES = { "sans-serif", "serif", "monospace" };
102 const std::set<std::string> QUALITY_TYPE = { "low", "medium", "high" }; // Default value is low.
103
GetJsDoubleVal(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value)104 inline double GetJsDoubleVal(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value)
105 {
106 if (!runtime || !value) {
107 LOGE("runtime or value is null.");
108 return 0.0;
109 }
110 if (value->IsNumber(runtime) || value->IsString(runtime)) {
111 return value->ToDouble(runtime);
112 }
113 return 0.0;
114 }
115
GetJsDashValue(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value)116 inline std::vector<double> GetJsDashValue(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value)
117 {
118 std::vector<double> segments;
119 if (!runtime || !value) {
120 LOGE("runtime or value is null.");
121 return segments;
122 }
123 auto valueStr = value->ToString(runtime);
124 std::vector<std::string> props;
125 StringUtils::StringSplitter(valueStr, ',', props);
126 for (const auto& prop : props) {
127 auto val = StringUtils::StringToDouble(prop);
128 // if there only exists 0 in props, it means that there is no dash style
129 if (NearZero(val) && props.size() == 1) {
130 return segments;
131 }
132 segments.emplace_back(val);
133 }
134 // if segment size is odd, copy one more to even
135 if (segments.size() % 2 != 0) {
136 segments.insert(segments.end(), segments.begin(), segments.end());
137 }
138 return segments;
139 }
140
GetJsRectParam(const shared_ptr<JsRuntime> & runtime,int32_t argc,const std::vector<shared_ptr<JsValue>> & argv)141 inline Rect GetJsRectParam(
142 const shared_ptr<JsRuntime>& runtime, int32_t argc, const std::vector<shared_ptr<JsValue>>& argv)
143 {
144 if (!runtime) {
145 LOGE("runtime is null.");
146 return Rect();
147 }
148 if (argc != 4) {
149 LOGE("argc error. argc = %{private}d", argc);
150 return Rect();
151 }
152 double x = GetJsDoubleVal(runtime, argv[0]);
153 double y = GetJsDoubleVal(runtime, argv[1]);
154 double width = GetJsDoubleVal(runtime, argv[2]);
155 double height = GetJsDoubleVal(runtime, argv[3]);
156 Rect rect = Rect(x, y, width, height);
157 return rect;
158 }
159
GetCurrentNodeId(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value)160 inline NodeId GetCurrentNodeId(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value)
161 {
162 if (!runtime || !value) {
163 LOGE("runtime or value is null.");
164 return 0;
165 }
166 NodeId id = 0;
167 auto nodeId = value->GetProperty(runtime, "__nodeId");
168 if (nodeId && nodeId->IsInt32(runtime)) {
169 id = nodeId->ToInt32(runtime);
170 }
171 return id < 0 ? 0 : id;
172 }
173
PushTaskToPage(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::function<void (const RefPtr<CanvasTaskPool> &)> & task)174 void PushTaskToPage(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
175 const std::function<void(const RefPtr<CanvasTaskPool>&)>& task)
176 {
177 if (!runtime || !value) {
178 LOGE("runtime or value is null.");
179 return;
180 }
181 // get node id
182 NodeId id = GetCurrentNodeId(runtime, value);
183 auto command = Referenced::MakeRefPtr<JsCommandContextOperation>(id, task);
184 // push command
185 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
186 if (!engine) {
187 LOGE("engine is null.");
188 return;
189 }
190 auto page = engine->GetRunningPage();
191 if (!page) {
192 LOGE("page is null.");
193 return;
194 }
195 page->PushCommand(command);
196 }
197
JsParseTextState(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value)198 inline PaintState JsParseTextState(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value)
199 {
200 PaintState state;
201 auto fontStyle = value->GetProperty(runtime, "font");
202 auto textAlign = value->GetProperty(runtime, "textAlign");
203 auto textBaseline = value->GetProperty(runtime, "textBaseline");
204
205 // parse font styles
206 auto alignStr = textAlign->ToString(runtime);
207 auto baselineStr = textBaseline->ToString(runtime);
208 auto fontStr = fontStyle->ToString(runtime);
209 state.SetTextAlign(ConvertStrToTextAlign(alignStr));
210 TextStyle style;
211 style.SetTextBaseline(
212 ConvertStrToEnum(baselineStr.c_str(), BASELINE_TABLE, ArraySize(BASELINE_TABLE), TextBaseline::ALPHABETIC));
213 std::vector<std::string> fontProps;
214 StringUtils::StringSplitter(fontStr, ' ', fontProps);
215 bool updateFontStyle = false;
216 for (const auto& fontProp : fontProps) {
217 if (FONT_WEIGHTS.find(fontProp) != FONT_WEIGHTS.end()) {
218 style.SetFontWeight(ConvertStrToFontWeight(fontProp));
219 } else if (FONT_STYLES.find(fontProp) != FONT_STYLES.end()) {
220 updateFontStyle = true;
221 style.SetFontStyle(ConvertStrToFontStyle(fontProp));
222 } else if (FONT_FAMILIES.find(fontProp) != FONT_FAMILIES.end()) {
223 style.SetFontFamilies(ConvertStrToFontFamilies(fontProp));
224 } else if (fontProp.find("px") != std::string::npos) {
225 std::string fontSize = fontProp.substr(0, fontProp.size() - 2);
226 style.SetFontSize(Dimension(StringToDouble(fontProp)));
227 } else {
228 LOGW("parse text error");
229 }
230 }
231 if (!updateFontStyle) {
232 auto task = [](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateFontStyle(FontStyle::NORMAL); };
233 PushTaskToPage(runtime, value, task);
234 }
235 state.SetTextStyle(style);
236 return state;
237 }
238
239 } // namespace
240
241 int32_t JsiCanvasBridge::gradientCount_ = 0;
242 int32_t JsiCanvasBridge::patternCount_ = 0;
243 int32_t JsiCanvasBridge::path2dCount_ = 0;
244 std::unordered_map<int32_t, Pattern> JsiCanvasBridge::pattern_;
245 std::unordered_map<int32_t, Gradient> JsiCanvasBridge::gradientColors_;
246 std::unordered_map<int32_t, RefPtr<CanvasPath2D>> JsiCanvasBridge::path2Ds_;
247
~JsiCanvasBridge()248 JsiCanvasBridge::~JsiCanvasBridge()
249 {
250 if (webglRenderContext_) {
251 delete webglRenderContext_;
252 webglRenderContext_ = nullptr;
253 }
254 if (webgl2RenderContext_) {
255 delete webgl2RenderContext_;
256 webgl2RenderContext_ = nullptr;
257 }
258 }
259
HandleJsContext(const shared_ptr<JsRuntime> & runtime,NodeId id,const std::string & args)260 void JsiCanvasBridge::HandleJsContext(const shared_ptr<JsRuntime>& runtime, NodeId id, const std::string& args)
261 {
262 std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(args);
263 if (argsValue && argsValue->IsArray() && argsValue->GetArraySize() > 0) {
264 auto typeArg = argsValue->GetArrayItem(0);
265 if (typeArg && typeArg->IsString()) {
266 std::string type = typeArg->GetString();
267 if (type == std::string(CANVAS_TYPE_WEBGL)) {
268 HandleWebglContext(runtime, id, args, webglRenderContext_);
269 return;
270 } else if (type == std::string(CANVAS_TYPE_WEBGL2)) {
271 HandleWebglContext(runtime, id, args, webgl2RenderContext_);
272 return;
273 }
274 }
275 }
276
277 renderContext_ = runtime->NewObject();
278 const std::vector<std::pair<const std::string, RegisterFunctionType>> contextTable = {
279 { "createLinearGradient", JsCreateLinearGradient },
280 { "createRadialGradient", JsCreateRadialGradient },
281 { "fillRect", JsFillRect },
282 { "strokeRect", JsStrokeRect },
283 { "clearRect", JsClearRect },
284 { "fillText", JsFillText },
285 { "strokeText", JsStrokeText },
286 { "measureText", JsMeasureText },
287 { "moveTo", JsMoveTo },
288 { "lineTo", JsLineTo },
289 { "bezierCurveTo", JsBezierCurveTo },
290 { "quadraticCurveTo", JsQuadraticCurveTo },
291 { "arcTo", JsArcTo },
292 { "arc", JsArc },
293 { "ellipse", JsEllipse },
294 { "fill", JsFill },
295 { "stroke", JsStroke },
296 { "clip", JsClip },
297 { "rect", JsRect },
298 { "beginPath", JsBeginPath },
299 { "closePath", JsClosePath },
300 { "restore", JsRestore },
301 { "save", JsSave },
302 { "rotate", JsRotate },
303 { "scale", JsScale },
304 { "setTransform", JsSetTransform },
305 { "transform", JsTransform },
306 { "translate", JsTranslate },
307 { "getLineDash", JsGetLineDash },
308 { "setLineDash", JsSetLineDash },
309 { "drawImage", JsDrawImage },
310 { "createPath2D", JsCreatePath2D },
311 { "createPattern", JsCreatePattern },
312 { "createImageData", JsCreateImageData },
313 { "putImageData", JsPutImageData },
314 { "getImageData", JsGetImageData },
315 #ifdef PIXEL_MAP_SUPPORTED
316 { "getPixelMap", JsGetPixelMap },
317 #endif
318 { "getJsonData", JsGetJsonData },
319 { "transferFromImageBitmap", JsTransferFromImageBitmap },
320 { "drawBitmapMesh", JsDrawBitmapMesh },
321 };
322 renderContext_->SetProperty(runtime, "__nodeId", runtime->NewInt32(id));
323 for (const auto& iter : contextTable) {
324 renderContext_->SetProperty(runtime, iter.first, runtime->NewFunction(iter.second));
325 }
326 static const std::vector<std::tuple<std::string, RegisterFunctionType, RegisterFunctionType>> animationFuncs = {
327 { "fillStyle", JsFillStyleGetter, JsFillStyleSetter },
328 { "strokeStyle", JsStrokeStyleGetter, JsStrokeStyleSetter },
329 { "lineCap", JsLineCapGetter, JsLineCapSetter },
330 { "lineJoin", JsLineJoinGetter, JsLineJoinSetter },
331 { "miterLimit", JsMiterLimitGetter, JsMiterLimitSetter },
332 { "lineWidth", JsLineWidthGetter, JsLineWidthSetter },
333 { "textAlign", JsTextAlignGetter, JsTextAlignSetter },
334 { "textBaseline", JsTextBaselineGetter, JsTextBaselineSetter },
335 { "font", JsFontGetter, JsFontSetter },
336 { "globalAlpha", JsAlphaGetter, JsAlphaSetter },
337 { "globalCompositeOperation", JsCompositeOperationGetter, JsCompositeOperationSetter },
338 { "lineDashOffset", JsLineDashOffsetGetter, JsLineDashOffsetSetter },
339 { "shadowBlur", JsShadowBlurGetter, JsShadowBlurSetter },
340 { "shadowColor", JsShadowColorGetter, JsShadowColorSetter },
341 { "shadowOffsetX", JsShadowOffsetXGetter, JsShadowOffsetXSetter },
342 { "shadowOffsetY", JsShadowOffsetYGetter, JsShadowOffsetYSetter },
343 { "imageSmoothingEnabled", JsSmoothingEnabledGetter, JsSmoothingEnabledSetter },
344 { "imageSmoothingQuality", JsSmoothingQualityGetter, JsSmoothingQualitySetter },
345 { "width", JsWidthGetter, nullptr },
346 { "height", JsHeightGetter, nullptr }
347 };
348 for (const auto& item : animationFuncs) {
349 auto getterTempl = runtime->NewFunction(std::get<1>(item));
350 auto setterTempl = runtime->NewFunction(std::get<2>(item));
351 bool ret = renderContext_->SetAccessorProperty(runtime, std::get<0>(item), getterTempl, setterTempl);
352 if (!ret) {
353 LOGE("Canvas set accessor property failed., name: %{public}s", std::get<0>(item).c_str());
354 }
355 }
356 JsSetAntiAlias(runtime, id, args);
357 }
358
HandleWebglContext(const shared_ptr<JsRuntime> & runtime,NodeId id,const std::string & args,CanvasRenderContextBase * & canvasRenderContext)359 void JsiCanvasBridge::HandleWebglContext(const shared_ptr<JsRuntime>& runtime,
360 NodeId id, const std::string& args, CanvasRenderContextBase*& canvasRenderContext)
361 {
362 #ifdef PREVIEW
363 LOGW("[Engine Log] Unable to use Webgl in the previewer. Perform this operation on the "
364 "emulator or a real device instead.");
365 renderContext_ = runtime->NewUndefined();
366 return;
367 #endif
368
369 renderContext_ = runtime->NewUndefined();
370 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
371 if (!engine) {
372 LOGE("engine is null.");
373 return;
374 }
375
376 auto nativeEngine = static_cast<ArkNativeEngine*>(engine->GetNativeEngine());
377 if (!nativeEngine) {
378 LOGE("NativeEngine is null");
379 return;
380 }
381
382 std::string moduleName(CANVAS_WEBGL_SO);
383 std::string pluginId(std::to_string(id));
384 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
385 LocalScope scope(pandaRuntime->GetEcmaVm());
386 auto obj = nativeEngine->GetModuleFromName(
387 moduleName, false, pluginId, args, WEBGL_RENDER_CONTEXT_NAME, reinterpret_cast<void**>(&canvasRenderContext));
388 if (!canvasRenderContext) {
389 LOGE("CanvasBridge invalid canvasRenderContext");
390 return;
391 }
392 if (obj.IsEmpty() || pandaRuntime->HasPendingException()) {
393 LOGE("Get local object failed.");
394 return;
395 }
396
397 renderContext_ = runtime->NewObject();
398 auto renderContext = std::static_pointer_cast<ArkJSValue>(renderContext_);
399 renderContext->SetValue(pandaRuntime, obj);
400
401 auto page = engine->GetRunningPage();
402 if (!page) {
403 LOGE("page is null.");
404 return;
405 }
406
407 auto task = [canvasRenderContext, page, id]() {
408 auto canvas = AceType::DynamicCast<DOMCanvas>(page->GetDomDocument()->GetDOMNodeById(id));
409 if (!canvas) {
410 return;
411 }
412 auto paintChild = AceType::DynamicCast<CustomPaintComponent>(canvas->GetSpecializedComponent());
413 if (paintChild) {
414 auto pool = paintChild->GetTaskPool();
415 if (!pool) {
416 return;
417 }
418 pool->WebGLInit(canvasRenderContext);
419 }
420 };
421
422 auto delegate = engine->GetFrontendDelegate();
423 if (!delegate) {
424 LOGE("ToDataURL failed. delegate is null.");
425 return;
426 }
427
428 delegate->PostSyncTaskToPage(task);
429
430 canvasRenderContext->Init();
431
432 auto canvas = AceType::DynamicCast<DOMCanvas>(page->GetDomDocument()->GetDOMNodeById(id));
433 if (!canvas) {
434 return;
435 }
436
437 auto paintChild = AceType::DynamicCast<CustomPaintComponent>(canvas->GetSpecializedComponent());
438 if (!paintChild) {
439 return;
440 }
441
442 auto pool = paintChild->GetTaskPool();
443 if (!pool) {
444 return;
445 }
446
447 auto weakDelegate = AceType::WeakClaim(AceType::RawPtr(delegate));
448 auto weakPool = AceType::WeakClaim(AceType::RawPtr(pool));
449
450 auto onWebGLUpdateCallback = [weakDelegate, weakPool]() {
451 auto delegate = weakDelegate.Upgrade();
452 if (delegate) {
453 auto task = [weakPool]() {
454 auto pool = weakPool.Upgrade();
455 if (pool) {
456 pool->WebGLUpdate();
457 }
458 };
459 delegate->PostUITask(task);
460 }
461 };
462 canvasRenderContext->SetUpdateCallback(onWebGLUpdateCallback);
463 }
464
HandleToDataURL(const shared_ptr<JsRuntime> & runtime,NodeId id,const std::string & args)465 void JsiCanvasBridge::HandleToDataURL(const shared_ptr<JsRuntime>& runtime, NodeId id, const std::string& args)
466 {
467 if (!runtime) {
468 LOGE("HandleToDataURL failed. runtime is null.");
469 return;
470 }
471 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
472 if (!engine) {
473 LOGE("HandleToDataURL failed. engine is null.");
474 return;
475 }
476 auto page = engine->GetRunningPage();
477 if (!page) {
478 LOGE("HandleToDataURL failed. page is null.");
479 return;
480 }
481 std::string dataUrl;
482 auto task = [id, page, args, &dataUrl]() {
483 auto canvas = AceType::DynamicCast<DOMCanvas>(page->GetDomDocument()->GetDOMNodeById(id));
484 if (!canvas) {
485 LOGE("ToDataURL failed, DOMCanvas is null.");
486 return;
487 }
488 auto paintChild = AceType::DynamicCast<CustomPaintComponent>(canvas->GetSpecializedComponent());
489 auto pool = paintChild->GetTaskPool();
490 if (!pool) {
491 LOGE("ToDataURL failed, TaskPool is null.");
492 return;
493 }
494 dataUrl = pool->ToDataURL(args);
495 };
496 auto delegate = engine->GetFrontendDelegate();
497 if (!delegate) {
498 LOGE("ToDataURL failed. delegate is null.");
499 return;
500 }
501 delegate->PostSyncTaskToPage(task);
502 dataURL_ = runtime->NewString(dataUrl);
503 }
504
JsSetAntiAlias(const shared_ptr<JsRuntime> & runtime,NodeId id,const std::string & args)505 void JsiCanvasBridge::JsSetAntiAlias(const shared_ptr<JsRuntime>& runtime, NodeId id, const std::string& args)
506 {
507 if (!runtime) {
508 LOGE("JsSetAntiAlias failed. runtime is null.");
509 return;
510 }
511 bool isEnabled = args.find("\"antialias\":true") != std::string::npos;
512 auto task = [isEnabled](const RefPtr<CanvasTaskPool>& pool) { pool->SetAntiAlias(isEnabled); };
513 auto command = Referenced::MakeRefPtr<JsCommandContextOperation>(id, task);
514 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
515 if (!engine) {
516 LOGE("JsSetAntiAlias failed. engine is null.");
517 return;
518 }
519 auto page = engine->GetRunningPage();
520 if (!page) {
521 LOGE("JsSetAntiAlias failed. page is null.");
522 return;
523 }
524 page->PushCommand(command);
525 auto delegate = engine->GetFrontendDelegate();
526 if (page->CheckPageCreated() && delegate) {
527 delegate->TriggerPageUpdate(page->GetPageId());
528 }
529 }
530
JsCreateLinearGradient(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)531 shared_ptr<JsValue> JsiCanvasBridge::JsCreateLinearGradient(const shared_ptr<JsRuntime>& runtime,
532 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
533 {
534 if (argc != 4) {
535 LOGE("argc error, argc = %{private}d", argc);
536 return runtime->NewUndefined();
537 }
538 shared_ptr<JsValue> gradient = runtime->NewObject();
539
540 gradient->SetProperty(runtime, "__type", runtime->NewString("gradient"));
541 gradient->SetProperty(runtime, "__id", runtime->NewInt32(gradientCount_));
542 gradient->SetProperty(runtime, "addColorStop", runtime->NewFunction(JsAddColorStop));
543
544 Offset beginOffset = Offset(GetJsDoubleVal(runtime, argv[0]), GetJsDoubleVal(runtime, argv[1]));
545 Offset endOffset = Offset(GetJsDoubleVal(runtime, argv[2]), GetJsDoubleVal(runtime, argv[3]));
546 gradientColors_[gradientCount_].SetBeginOffset(beginOffset);
547 gradientColors_[gradientCount_].SetEndOffset(endOffset);
548 ++gradientCount_;
549 return gradient;
550 }
551
JsCreateRadialGradient(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)552 shared_ptr<JsValue> JsiCanvasBridge::JsCreateRadialGradient(const shared_ptr<JsRuntime>& runtime,
553 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
554 {
555 // 6 parameters: createRadialGradient(x0, y0, r0, x1, y1, r1)
556 if (argc != 6) {
557 LOGE("argc error, argc = %{private}d", argc);
558 return runtime->NewUndefined();
559 }
560 shared_ptr<JsValue> gradient = runtime->NewObject();
561 gradient->SetProperty(runtime, "__type", runtime->NewString("gradient"));
562 gradient->SetProperty(runtime, "__id", runtime->NewInt32(gradientCount_));
563 gradient->SetProperty(runtime, "addColorStop", runtime->NewFunction(JsAddColorStop));
564 Offset innerCenter = Offset(GetJsDoubleVal(runtime, argv[0]), GetJsDoubleVal(runtime, argv[1]));
565 Offset outerCenter = Offset(GetJsDoubleVal(runtime, argv[3]), GetJsDoubleVal(runtime, argv[4]));
566 double innerRadius = GetJsDoubleVal(runtime, argv[2]);
567 double outerRadius = GetJsDoubleVal(runtime, argv[5]);
568 gradientColors_[gradientCount_].SetType(GradientType::RADIAL);
569 gradientColors_[gradientCount_].SetBeginOffset(innerCenter);
570 gradientColors_[gradientCount_].SetEndOffset(outerCenter);
571 gradientColors_[gradientCount_].SetInnerRadius(innerRadius);
572 gradientColors_[gradientCount_].SetOuterRadius(outerRadius);
573 ++gradientCount_;
574 return gradient;
575 }
576
JsAddColorStop(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)577 shared_ptr<JsValue> JsiCanvasBridge::JsAddColorStop(const shared_ptr<JsRuntime>& runtime,
578 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
579 {
580 if (argc != 2) {
581 LOGE("argc error, argc = %{private}d", argc);
582 return runtime->NewUndefined();
583 }
584
585 GradientColor color;
586 auto jsColor = argv[1]->ToString(runtime);
587 color.SetColor(Color::FromString(jsColor));
588 color.SetDimension(GetJsDoubleVal(runtime, argv[0]));
589 int32_t id = -1;
590 auto nodeId = value->GetProperty(runtime, "__id");
591 if (nodeId && nodeId->IsInt32(runtime)) {
592 id = nodeId->ToInt32(runtime);
593 }
594 if (id < 0) {
595 return runtime->NewUndefined();
596 }
597 gradientColors_[id].AddColor(color);
598 return runtime->NewUndefined();
599 }
600
GetGradient(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value)601 Gradient JsiCanvasBridge::GetGradient(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value)
602 {
603 int32_t id = -1;
604 auto nodeId = value->GetProperty(runtime, "__id");
605 if (nodeId && nodeId->IsInt32(runtime)) {
606 id = nodeId->ToInt32(runtime);
607 }
608 if (id < 0) {
609 return Gradient();
610 }
611 return gradientColors_[id];
612 }
613
JsFillRect(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)614 shared_ptr<JsValue> JsiCanvasBridge::JsFillRect(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
615 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
616 {
617 if (argc != 4) {
618 LOGE("argc error, argc = %{private}d", argc);
619 return runtime->NewUndefined();
620 }
621 Rect rect = GetJsRectParam(runtime, argc, argv);
622 auto task = [rect](const RefPtr<CanvasTaskPool>& pool) { pool->FillRect(rect); };
623 PushTaskToPage(runtime, value, std::move(task));
624 return runtime->NewUndefined();
625 }
626
JsStrokeRect(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)627 shared_ptr<JsValue> JsiCanvasBridge::JsStrokeRect(const shared_ptr<JsRuntime>& runtime,
628 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
629 {
630 if (argc != 4) {
631 LOGE("argc error, argc = %{private}d", argc);
632 return runtime->NewUndefined();
633 }
634 Rect rect = GetJsRectParam(runtime, argc, argv);
635 auto task = [rect](const RefPtr<CanvasTaskPool>& pool) { pool->StrokeRect(rect); };
636 PushTaskToPage(runtime, value, std::move(task));
637 return runtime->NewUndefined();
638 }
639
JsClearRect(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)640 shared_ptr<JsValue> JsiCanvasBridge::JsClearRect(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
641 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
642 {
643 if (argc != 4) {
644 LOGE("argc error, argc = %{private}d", argc);
645 return runtime->NewUndefined();
646 }
647 Rect rect = GetJsRectParam(runtime, argc, argv);
648 auto task = [rect](const RefPtr<CanvasTaskPool>& pool) { pool->ClearRect(rect); };
649 PushTaskToPage(runtime, value, task);
650 return runtime->NewUndefined();
651 }
652
JsFillText(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)653 shared_ptr<JsValue> JsiCanvasBridge::JsFillText(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
654 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
655 {
656 if (argc != 3) {
657 LOGE("argc error, argc = %{private}d", argc);
658 return runtime->NewUndefined();
659 }
660 if (!argv[0]) {
661 return runtime->NewUndefined();
662 }
663 auto text = argv[0]->ToString(runtime);
664 double x = GetJsDoubleVal(runtime, argv[1]);
665 double y = GetJsDoubleVal(runtime, argv[2]);
666 auto task = [text, x, y](const RefPtr<CanvasTaskPool>& pool) { pool->FillText(text, Offset(x, y)); };
667 PushTaskToPage(runtime, value, task);
668 return runtime->NewUndefined();
669 }
670
JsStrokeText(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)671 shared_ptr<JsValue> JsiCanvasBridge::JsStrokeText(const shared_ptr<JsRuntime>& runtime,
672 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
673 {
674 if (argc != 3) {
675 LOGE("argc error, argc = %{private}d", argc);
676 return runtime->NewUndefined();
677 }
678 if (!argv[0]) {
679 return runtime->NewUndefined();
680 }
681 auto text = argv[0]->ToString(runtime);
682 double x = GetJsDoubleVal(runtime, argv[1]);
683 double y = GetJsDoubleVal(runtime, argv[2]);
684 auto task = [text, x, y](const RefPtr<CanvasTaskPool>& pool) { pool->StrokeText(text, Offset(x, y)); };
685 PushTaskToPage(runtime, value, task);
686 return runtime->NewUndefined();
687 }
688
JsMeasureText(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)689 shared_ptr<JsValue> JsiCanvasBridge::JsMeasureText(const shared_ptr<JsRuntime>& runtime,
690 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
691 {
692 // this func should return TextMetrics, including the width of the text
693 if (argc != 1) {
694 LOGE("argc error, argc = %{private}d", argc);
695 return runtime->NewUndefined();
696 }
697 if (!argv[0]) {
698 return runtime->NewUndefined();
699 }
700 auto text = argv[0]->ToString(runtime);
701 auto textState = JsParseTextState(runtime, value);
702 NodeId id = GetCurrentNodeId(runtime, value);
703 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
704 if (!engine) {
705 LOGE("JsMeasureText failed. engine is null.");
706 return runtime->NewUndefined();
707 }
708 auto page = engine->GetRunningPage();
709 if (!page) {
710 LOGE("JsMeasureText failed. page is null.");
711 return runtime->NewUndefined();
712 }
713 double width = 0.0;
714 double height = 0.0;
715 auto task = [&text, &textState, id, page, &width, &height]() {
716 auto canvas = AceType::DynamicCast<DOMCanvas>(page->GetDomDocument()->GetDOMNodeById(id));
717 if (!canvas) {
718 return;
719 }
720 auto paintChild = AceType::DynamicCast<CustomPaintComponent>(canvas->GetSpecializedComponent());
721 auto canvasTask = paintChild->GetTaskPool();
722 if (!canvasTask) {
723 return;
724 }
725 width = canvasTask->MeasureText(text, textState);
726 height = canvasTask->MeasureTextHeight(text, textState);
727 };
728 auto delegate = engine->GetFrontendDelegate();
729 if (!delegate) {
730 LOGE("JsMeasureText failed. delegate is null.");
731 return runtime->NewUndefined();
732 }
733 delegate->PostSyncTaskToPage(task);
734 auto textMetrics = runtime->NewObject();
735 textMetrics->SetProperty(runtime, "width", runtime->NewNumber(width));
736 textMetrics->SetProperty(runtime, "height", runtime->NewNumber(height));
737 return textMetrics;
738 }
739
JsBeginPath(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)740 shared_ptr<JsValue> JsiCanvasBridge::JsBeginPath(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
741 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
742 {
743 if (argc != 0) {
744 LOGE("argc error, argc = %{private}d", argc);
745 return runtime->NewUndefined();
746 }
747 auto task = [](const RefPtr<CanvasTaskPool>& pool) { pool->BeginPath(); };
748 PushTaskToPage(runtime, value, task);
749 return runtime->NewUndefined();
750 }
751
JsClosePath(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)752 shared_ptr<JsValue> JsiCanvasBridge::JsClosePath(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
753 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
754 {
755 if (argc != 0) {
756 LOGE("argc error, argc = %{private}d", argc);
757 return runtime->NewUndefined();
758 }
759 auto task = [](const RefPtr<CanvasTaskPool>& pool) { pool->ClosePath(); };
760 PushTaskToPage(runtime, value, task);
761 return runtime->NewUndefined();
762 }
763
JsMoveTo(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)764 shared_ptr<JsValue> JsiCanvasBridge::JsMoveTo(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
765 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
766 {
767 if (argc != 2) {
768 LOGE("argc error, argc = %{private}d", argc);
769 return runtime->NewUndefined();
770 }
771 double x = GetJsDoubleVal(runtime, argv[0]);
772 double y = GetJsDoubleVal(runtime, argv[1]);
773 auto task = [x, y](const RefPtr<CanvasTaskPool>& pool) { pool->MoveTo(x, y); };
774 PushTaskToPage(runtime, value, task);
775 return runtime->NewUndefined();
776 }
777
JsLineTo(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)778 shared_ptr<JsValue> JsiCanvasBridge::JsLineTo(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
779 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
780 {
781 if (argc != 2) {
782 LOGE("argc error, argc = %{private}d", argc);
783 return runtime->NewUndefined();
784 }
785 double x = GetJsDoubleVal(runtime, argv[0]);
786 double y = GetJsDoubleVal(runtime, argv[1]);
787 auto task = [x, y](const RefPtr<CanvasTaskPool>& pool) { pool->LineTo(x, y); };
788 PushTaskToPage(runtime, value, task);
789 return runtime->NewUndefined();
790 }
791
JsBezierCurveTo(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)792 shared_ptr<JsValue> JsiCanvasBridge::JsBezierCurveTo(const shared_ptr<JsRuntime>& runtime,
793 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
794 {
795 if (argc != 6) {
796 LOGE("argc error, argc = %{private}d", argc);
797 return runtime->NewUndefined();
798 }
799 BezierCurveParam param;
800 param.cp1x = GetJsDoubleVal(runtime, argv[0]);
801 param.cp1y = GetJsDoubleVal(runtime, argv[1]);
802 param.cp2x = GetJsDoubleVal(runtime, argv[2]);
803 param.cp2y = GetJsDoubleVal(runtime, argv[3]);
804 param.x = GetJsDoubleVal(runtime, argv[4]);
805 param.y = GetJsDoubleVal(runtime, argv[5]);
806 auto task = [param](const RefPtr<CanvasTaskPool>& pool) { pool->BezierCurveTo(param); };
807 PushTaskToPage(runtime, value, task);
808 return runtime->NewUndefined();
809 }
810
JsQuadraticCurveTo(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)811 shared_ptr<JsValue> JsiCanvasBridge::JsQuadraticCurveTo(const shared_ptr<JsRuntime>& runtime,
812 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
813 {
814 if (argc != 4) {
815 LOGE("argc error, argc = %{private}d", argc);
816 return runtime->NewUndefined();
817 }
818 QuadraticCurveParam param;
819 param.cpx = GetJsDoubleVal(runtime, argv[0]);
820 param.cpy = GetJsDoubleVal(runtime, argv[1]);
821 param.x = GetJsDoubleVal(runtime, argv[2]);
822 param.y = GetJsDoubleVal(runtime, argv[3]);
823 auto task = [param](const RefPtr<CanvasTaskPool>& pool) { pool->QuadraticCurveTo(param); };
824 PushTaskToPage(runtime, value, task);
825 return runtime->NewUndefined();
826 }
827
JsArc(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)828 shared_ptr<JsValue> JsiCanvasBridge::JsArc(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
829 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
830 {
831 if (argc < 5 || argc > 6) {
832 LOGE("argc error, argc = %{private}d", argc);
833 return runtime->NewUndefined();
834 }
835 ArcParam param;
836 param.x = GetJsDoubleVal(runtime, argv[0]);
837 param.y = GetJsDoubleVal(runtime, argv[1]);
838 param.radius = GetJsDoubleVal(runtime, argv[2]);
839 param.startAngle = GetJsDoubleVal(runtime, argv[3]);
840 param.endAngle = GetJsDoubleVal(runtime, argv[4]);
841 if (argc == 6) {
842 if (!argv[5]) {
843 LOGW("no value");
844 return runtime->NewUndefined();
845 }
846 std::unique_ptr<JsonValue> argPtr = JsonUtil::ParseJsonString(argv[5]->ToString(runtime));
847 if (argPtr && argPtr->IsBool()) {
848 param.anticlockwise = argPtr->GetBool();
849 }
850 }
851 auto task = [param](const RefPtr<CanvasTaskPool>& pool) { pool->Arc(param); };
852 PushTaskToPage(runtime, value, task);
853 return runtime->NewUndefined();
854 }
855
JsArcTo(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)856 shared_ptr<JsValue> JsiCanvasBridge::JsArcTo(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
857 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
858 {
859 if (argc != 5) {
860 LOGE("argc error, argc = %{private}d", argc);
861 return runtime->NewUndefined();
862 }
863 ArcToParam param;
864 param.x1 = GetJsDoubleVal(runtime, argv[0]);
865 param.y1 = GetJsDoubleVal(runtime, argv[1]);
866 param.x2 = GetJsDoubleVal(runtime, argv[2]);
867 param.y2 = GetJsDoubleVal(runtime, argv[3]);
868 param.radius = GetJsDoubleVal(runtime, argv[4]);
869 auto task = [param](const RefPtr<CanvasTaskPool>& pool) { pool->ArcTo(param); };
870 PushTaskToPage(runtime, value, task);
871 return runtime->NewUndefined();
872 }
873
JsEllipse(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)874 shared_ptr<JsValue> JsiCanvasBridge::JsEllipse(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
875 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
876 {
877 // 7 or 8 parameters: ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise?)
878 if (argc < 7 || argc > 8) {
879 LOGE("argc error, argc = %{private}d", argc);
880 return runtime->NewUndefined();
881 }
882 EllipseParam param;
883 param.x = GetJsDoubleVal(runtime, argv[0]);
884 param.y = GetJsDoubleVal(runtime, argv[1]);
885 param.radiusX = GetJsDoubleVal(runtime, argv[2]);
886 param.radiusY = GetJsDoubleVal(runtime, argv[3]);
887 param.rotation = GetJsDoubleVal(runtime, argv[4]);
888 param.startAngle = GetJsDoubleVal(runtime, argv[5]);
889 param.endAngle = GetJsDoubleVal(runtime, argv[6]);
890 if (argc == 8) {
891 int32_t anti = static_cast<int32_t>(GetJsDoubleVal(runtime, argv[7]));
892 param.anticlockwise = (anti == 1);
893 }
894 auto task = [param](const RefPtr<CanvasTaskPool>& pool) { pool->Ellipse(param); };
895 PushTaskToPage(runtime, value, task);
896 return runtime->NewUndefined();
897 }
898
JsRect(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)899 shared_ptr<JsValue> JsiCanvasBridge::JsRect(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
900 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
901 {
902 Rect rect = GetJsRectParam(runtime, argc, argv);
903 auto task = [rect](const RefPtr<CanvasTaskPool>& pool) { pool->AddRect(rect); };
904 PushTaskToPage(runtime, value, std::move(task));
905 return runtime->NewUndefined();
906 }
907
JsFill(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)908 shared_ptr<JsValue> JsiCanvasBridge::JsFill(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
909 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
910 {
911 auto task = [](const RefPtr<CanvasTaskPool>& pool) { pool->Fill(); };
912 PushTaskToPage(runtime, value, task);
913 return runtime->NewUndefined();
914 }
915
JsStroke(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)916 shared_ptr<JsValue> JsiCanvasBridge::JsStroke(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
917 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
918 {
919 // 0 or 1 parameter: ctx.stroke() / ctx.stroke(path)
920 if (argc == 1) {
921 auto typeVal = argv[0]->GetProperty(runtime, "__type");
922 auto type = typeVal->ToString(runtime);
923 if (type != "path2d") {
924 LOGE("Stroke Path2D failed, target is not path.");
925 return runtime->NewUndefined();
926 }
927 auto path = GetPath2D(runtime, argv[0]);
928 if (path == nullptr) {
929 LOGE("Stroke Path2D failed, target path is null.");
930 return runtime->NewUndefined();
931 }
932 auto task = [path](const RefPtr<CanvasTaskPool>& pool) { pool->Stroke(path); };
933 PushTaskToPage(runtime, value, task);
934 return runtime->NewUndefined();
935 }
936 auto task = [](const RefPtr<CanvasTaskPool>& pool) { pool->Stroke(); };
937 PushTaskToPage(runtime, value, task);
938 return runtime->NewUndefined();
939 }
940
JsClip(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)941 shared_ptr<JsValue> JsiCanvasBridge::JsClip(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
942 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
943 {
944 auto task = [](const RefPtr<CanvasTaskPool>& pool) { pool->Clip(); };
945 PushTaskToPage(runtime, value, task);
946 return runtime->NewUndefined();
947 }
948
JsRestore(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)949 shared_ptr<JsValue> JsiCanvasBridge::JsRestore(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
950 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
951 {
952 if (argc != 0) {
953 LOGE("argc error, argc = %{private}d", argc);
954 return runtime->NewUndefined();
955 }
956 auto task = [](const RefPtr<CanvasTaskPool>& pool) { pool->Restore(); };
957 PushTaskToPage(runtime, value, task);
958 return runtime->NewUndefined();
959 }
960
JsSave(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)961 shared_ptr<JsValue> JsiCanvasBridge::JsSave(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
962 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
963 {
964 if (argc != 0) {
965 LOGE("argc error, argc = %{private}d", argc);
966 return runtime->NewUndefined();
967 }
968 auto task = [](const RefPtr<CanvasTaskPool>& pool) { pool->Save(); };
969 PushTaskToPage(runtime, value, task);
970 return runtime->NewUndefined();
971 }
972
JsRotate(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)973 shared_ptr<JsValue> JsiCanvasBridge::JsRotate(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
974 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
975 {
976 double angle = GetJsDoubleVal(runtime, argv[0]);
977 auto task = [angle](const RefPtr<CanvasTaskPool>& pool) { pool->Rotate(angle); };
978 PushTaskToPage(runtime, value, task);
979 return runtime->NewUndefined();
980 }
981
JsScale(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)982 shared_ptr<JsValue> JsiCanvasBridge::JsScale(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
983 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
984 {
985 if (argc != 2) {
986 LOGE("argc error, argc = %{private}d", argc);
987 return runtime->NewUndefined();
988 }
989 double x = GetJsDoubleVal(runtime, argv[0]);
990 double y = GetJsDoubleVal(runtime, argv[1]);
991 auto task = [x, y](const RefPtr<CanvasTaskPool>& pool) { pool->Scale(x, y); };
992 PushTaskToPage(runtime, value, task);
993 return runtime->NewUndefined();
994 }
995
JsSetTransform(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)996 shared_ptr<JsValue> JsiCanvasBridge::JsSetTransform(const shared_ptr<JsRuntime>& runtime,
997 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
998 {
999 if (argc != 6) {
1000 LOGE("argc error, argc = %{private}d", argc);
1001 return runtime->NewUndefined();
1002 }
1003 TransformParam param;
1004 param.scaleX = GetJsDoubleVal(runtime, argv[0]);
1005 param.skewX = GetJsDoubleVal(runtime, argv[1]);
1006 param.skewY = GetJsDoubleVal(runtime, argv[2]);
1007 param.scaleY = GetJsDoubleVal(runtime, argv[3]);
1008 param.translateX = GetJsDoubleVal(runtime, argv[4]);
1009 param.translateY = GetJsDoubleVal(runtime, argv[5]);
1010 auto task = [param](const RefPtr<CanvasTaskPool>& pool) { pool->SetTransform(param); };
1011 PushTaskToPage(runtime, value, task);
1012 return runtime->NewUndefined();
1013 }
1014
JsTransform(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1015 shared_ptr<JsValue> JsiCanvasBridge::JsTransform(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
1016 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1017 {
1018 if (argc != 6) {
1019 LOGE("argc error, argc = %{private}d", argc);
1020 return runtime->NewUndefined();
1021 }
1022 TransformParam param;
1023 param.scaleX = GetJsDoubleVal(runtime, argv[0]);
1024 param.skewX = GetJsDoubleVal(runtime, argv[1]);
1025 param.skewY = GetJsDoubleVal(runtime, argv[2]);
1026 param.scaleY = GetJsDoubleVal(runtime, argv[3]);
1027 param.translateX = GetJsDoubleVal(runtime, argv[4]);
1028 param.translateY = GetJsDoubleVal(runtime, argv[5]);
1029 auto task = [param](const RefPtr<CanvasTaskPool>& pool) { pool->Transform(param); };
1030 PushTaskToPage(runtime, value, task);
1031 return runtime->NewUndefined();
1032 }
1033
JsTranslate(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1034 shared_ptr<JsValue> JsiCanvasBridge::JsTranslate(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
1035 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1036 {
1037 if (argc != 2) {
1038 LOGE("argc error, argc = %{private}d", argc);
1039 return runtime->NewUndefined();
1040 }
1041 double x = GetJsDoubleVal(runtime, argv[0]);
1042 double y = GetJsDoubleVal(runtime, argv[1]);
1043 auto task = [x, y](const RefPtr<CanvasTaskPool>& pool) { pool->Translate(x, y); };
1044 PushTaskToPage(runtime, value, task);
1045 return runtime->NewUndefined();
1046 }
1047
JsSetLineDash(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1048 shared_ptr<JsValue> JsiCanvasBridge::JsSetLineDash(const shared_ptr<JsRuntime>& runtime,
1049 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1050 {
1051 if (argc != 1) {
1052 LOGE("argc error, argc = %{private}d", argc);
1053 return runtime->NewUndefined();
1054 }
1055 auto dash = argv[0]->ToString(runtime);
1056 value->SetProperty(runtime, "lineDash", runtime->NewString(dash));
1057 auto segments = GetJsDashValue(runtime, argv[0]);
1058 auto task = [segments](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateLineDash(segments); };
1059 PushTaskToPage(runtime, value, task);
1060 return runtime->NewUndefined();
1061 }
1062
JsGetLineDash(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1063 shared_ptr<JsValue> JsiCanvasBridge::JsGetLineDash(const shared_ptr<JsRuntime>& runtime,
1064 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1065 {
1066 if (argc != 0) {
1067 LOGE("argc error, argc = %{private}d", argc);
1068 return runtime->NewUndefined();
1069 }
1070 auto val = value->GetProperty(runtime, "lineDash");
1071 return val;
1072 }
1073
ParseDomImage(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,double & width,double & height,std::string & src)1074 void JsiCanvasBridge::ParseDomImage(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
1075 double& width, double& height, std::string& src)
1076 {
1077 auto jsAttr = value->GetProperty(runtime, "attr");
1078 auto jsSrc = jsAttr->GetProperty(runtime, DOM_SRC);
1079 auto imgSrc = jsSrc->ToString(runtime);
1080 src = imgSrc;
1081
1082 auto jsStyle = value->GetProperty(runtime, "style");
1083 auto jsWidth = jsStyle->GetProperty(runtime, DOM_WIDTH);
1084 auto jsHeight = jsStyle->GetProperty(runtime, DOM_HEIGHT);
1085 auto cWidth = jsWidth->ToString(runtime);
1086 auto cHeight = jsHeight->ToString(runtime);
1087 width = StringToDouble(cWidth);
1088 height = StringToDouble(cHeight);
1089
1090 if (NearZero(width)) {
1091 width = StringToDouble(cWidth.substr(0, cWidth.size() - 2)); // remove px units
1092 }
1093 if (NearZero(height)) {
1094 height = StringToDouble(cHeight.substr(0, cHeight.size() - 2));
1095 }
1096 }
1097
JsDrawImage(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1098 shared_ptr<JsValue> JsiCanvasBridge::JsDrawImage(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
1099 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1100 {
1101 if (!argv[0] || !argv[0]->IsObject(runtime)) {
1102 return runtime->NewUndefined();
1103 }
1104
1105 RefPtr<PixelMap> pixelMap = nullptr;
1106 bool isPixelMap = false;
1107
1108 CanvasImage image;
1109 double width = 0.0;
1110 double height = 0.0;
1111 auto src = argv[0]->GetProperty(runtime, DOM_SRC);
1112 if (src->IsUndefined(runtime)) {
1113 #if !defined(PREVIEW)
1114 pixelMap = CreatePixelMapFromNapiValue(runtime, argv[0]);
1115 if (!pixelMap) {
1116 LOGE("pixelMap is null");
1117 return runtime->NewUndefined();
1118 }
1119 isPixelMap = true;
1120 #else
1121 return runtime->NewUndefined();
1122 #endif
1123 } else if (!src->IsString(runtime)) {
1124 ParseDomImage(runtime, argv[0], width, height, image.src);
1125 } else {
1126 auto imgSrc = src->ToString(runtime);
1127 image.src = imgSrc;
1128 auto jsWidth = argv[0]->GetProperty(runtime, DOM_WIDTH);
1129 auto jsHeight = argv[0]->GetProperty(runtime, DOM_HEIGHT);
1130 width = jsWidth->ToDouble(runtime);
1131 height = jsHeight->ToDouble(runtime);
1132 }
1133 switch (argc) {
1134 case 3:
1135 image.flag = 0;
1136 image.dx = GetJsDoubleVal(runtime, argv[1]);
1137 image.dy = GetJsDoubleVal(runtime, argv[2]);
1138 break;
1139 case 5:
1140 image.flag = 1;
1141 image.dx = GetJsDoubleVal(runtime, argv[1]);
1142 image.dy = GetJsDoubleVal(runtime, argv[2]);
1143 image.dWidth = GetJsDoubleVal(runtime, argv[3]);
1144 image.dHeight = GetJsDoubleVal(runtime, argv[4]);
1145 break;
1146 case 9:
1147 image.flag = 2;
1148 image.sx = GetJsDoubleVal(runtime, argv[1]);
1149 image.sy = GetJsDoubleVal(runtime, argv[2]);
1150 image.sWidth = GetJsDoubleVal(runtime, argv[3]);
1151 image.sHeight = GetJsDoubleVal(runtime, argv[4]);
1152 image.dx = GetJsDoubleVal(runtime, argv[5]);
1153 image.dy = GetJsDoubleVal(runtime, argv[6]);
1154 image.dWidth = GetJsDoubleVal(runtime, argv[7]);
1155 image.dHeight = GetJsDoubleVal(runtime, argv[8]);
1156 break;
1157 default:
1158 break;
1159 }
1160 auto task = [image, width, height, isPixelMap, pixelMap](const RefPtr<CanvasTaskPool>& pool) {
1161 if (isPixelMap) {
1162 pool->DrawPixelMap(pixelMap, image);
1163 } else {
1164 pool->DrawImage(image, width, height);
1165 }
1166 };
1167 PushTaskToPage(runtime, value, task);
1168 return runtime->NewUndefined();
1169 }
1170
JsCreatePath2D(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1171 shared_ptr<JsValue> JsiCanvasBridge::JsCreatePath2D(const shared_ptr<JsRuntime>& runtime,
1172 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1173 {
1174 shared_ptr<JsValue> path2D = runtime->NewObject();
1175 path2D->SetProperty(runtime, "__type", runtime->NewString("path2d"));
1176 path2D->SetProperty(runtime, "__id", runtime->NewInt32(path2dCount_));
1177 path2D->SetProperty(runtime, "addPath", runtime->NewFunction(JsPath2DAddPath));
1178 path2D->SetProperty(runtime, "setTransform", runtime->NewFunction(JsPath2DSetTransform));
1179 path2D->SetProperty(runtime, "moveTo", runtime->NewFunction(JsPath2DMoveTo));
1180 path2D->SetProperty(runtime, "lineTo", runtime->NewFunction(JsPath2DLineTo));
1181 path2D->SetProperty(runtime, "arc", runtime->NewFunction(JsPath2DArc));
1182 path2D->SetProperty(runtime, "arcTo", runtime->NewFunction(JsPath2DArcTo));
1183 path2D->SetProperty(runtime, "quadraticCurveTo", runtime->NewFunction(JsPath2DQuadraticCurveTo));
1184 path2D->SetProperty(runtime, "bezierCurveTo", runtime->NewFunction(JsPath2DBezierCurveTo));
1185 path2D->SetProperty(runtime, "ellipse", runtime->NewFunction(JsPath2DEllipse));
1186 path2D->SetProperty(runtime, "rect", runtime->NewFunction(JsPath2DRect));
1187 path2D->SetProperty(runtime, "closePath", runtime->NewFunction(JsPath2DClosePath));
1188 path2Ds_[path2dCount_] = JsMakePath2D(runtime, value, argv, argc);
1189 ++path2dCount_;
1190 return path2D;
1191 }
1192
JsPath2DAddPath(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1193 shared_ptr<JsValue> JsiCanvasBridge::JsPath2DAddPath(const shared_ptr<JsRuntime>& runtime,
1194 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1195 {
1196 // 1 parameter: addPath(path)
1197 if (argc != 1) {
1198 LOGE("AddPath to Path2D failed, invalid args.");
1199 return runtime->NewUndefined();
1200 }
1201 int32_t id = -1;
1202 auto nodeId = value->GetProperty(runtime, "__id");
1203 if (nodeId && nodeId->IsInt32(runtime)) {
1204 id = nodeId->ToInt32(runtime);
1205 }
1206 if (id < 0) {
1207 return runtime->NewUndefined();
1208 }
1209 auto holderPath = path2Ds_[id];
1210 if (holderPath == nullptr) {
1211 LOGE("AddPath to Path2D failed, holderPath is null.");
1212 return runtime->NewUndefined();
1213 }
1214 auto typeVal = argv[0]->GetProperty(runtime, "__type");
1215 auto type = typeVal->ToString(runtime);
1216 if (type != "path2d") {
1217 LOGE("Stroke Path2D failed, target is not path.");
1218 return runtime->NewUndefined();
1219 }
1220 auto toBeAdd = GetPath2D(runtime, argv[0]);
1221 if (toBeAdd == nullptr) {
1222 LOGE("AddPath to Path2D failed, to be added path is null.");
1223 return runtime->NewUndefined();
1224 }
1225 holderPath->AddPath(toBeAdd);
1226 return runtime->NewUndefined();
1227 }
1228
JsPath2DSetTransform(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1229 shared_ptr<JsValue> JsiCanvasBridge::JsPath2DSetTransform(const shared_ptr<JsRuntime>& runtime,
1230 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1231 {
1232 // 6 parameters: setTransform(a, b, c, d, e, f)
1233 if (argc != 6) {
1234 LOGE("Call Path2D SetTransform failed, invalid args.");
1235 return runtime->NewUndefined();
1236 }
1237 int32_t id = -1;
1238 auto nodeId = value->GetProperty(runtime, "__id");
1239 if (nodeId && nodeId->IsInt32(runtime)) {
1240 id = nodeId->ToInt32(runtime);
1241 }
1242 if (id < 0) {
1243 return runtime->NewUndefined();
1244 }
1245 auto holderPath = path2Ds_[id];
1246 if (holderPath == nullptr) {
1247 LOGE("Call Path2D SetTransform failed, holderPath is null.");
1248 return runtime->NewUndefined();
1249 }
1250 holderPath->SetTransform(GetJsDoubleVal(runtime, argv[0]), GetJsDoubleVal(runtime, argv[1]),
1251 GetJsDoubleVal(runtime, argv[2]), GetJsDoubleVal(runtime, argv[3]),
1252 GetJsDoubleVal(runtime, argv[4]), GetJsDoubleVal(runtime, argv[5]));
1253 return runtime->NewUndefined();
1254 }
1255
JsPath2DMoveTo(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1256 shared_ptr<JsValue> JsiCanvasBridge::JsPath2DMoveTo(const shared_ptr<JsRuntime>& runtime,
1257 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1258 {
1259 // 2 parameters: moveTo(x, y)
1260 if (argc != 2) {
1261 LOGE("Call Path2D Arc MoveTo, invalid args.");
1262 return runtime->NewUndefined();
1263 }
1264 int32_t id = -1;
1265 auto nodeId = value->GetProperty(runtime, "__id");
1266 if (nodeId && nodeId->IsInt32(runtime)) {
1267 id = nodeId->ToInt32(runtime);
1268 }
1269 if (id < 0) {
1270 return runtime->NewUndefined();
1271 }
1272 auto holderPath = path2Ds_[id];
1273 if (holderPath == nullptr) {
1274 LOGE("Call Path2D MoveTo failed, holderPath is null.");
1275 return runtime->NewUndefined();
1276 }
1277 holderPath->MoveTo(GetJsDoubleVal(runtime, argv[0]), GetJsDoubleVal(runtime, argv[1]));
1278 return runtime->NewUndefined();
1279 }
1280
JsPath2DLineTo(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1281 shared_ptr<JsValue> JsiCanvasBridge::JsPath2DLineTo(const shared_ptr<JsRuntime>& runtime,
1282 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1283 {
1284 // 2 parameters: lineTo(x, y)
1285 if (argc != 2) {
1286 LOGE("Call Path2D LineTo failed, invalid args.");
1287 return runtime->NewUndefined();
1288 }
1289 int32_t id = -1;
1290 auto nodeId = value->GetProperty(runtime, "__id");
1291 if (nodeId && nodeId->IsInt32(runtime)) {
1292 id = nodeId->ToInt32(runtime);
1293 }
1294 if (id < 0) {
1295 return runtime->NewUndefined();
1296 }
1297 auto holderPath = path2Ds_[id];
1298 if (holderPath == nullptr) {
1299 LOGE("Call Path2D LineTo failed, holderPath is null.");
1300 return runtime->NewUndefined();
1301 }
1302 holderPath->LineTo(GetJsDoubleVal(runtime, argv[0]), GetJsDoubleVal(runtime, argv[1]));
1303 return runtime->NewUndefined();
1304 }
1305
JsPath2DArc(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1306 shared_ptr<JsValue> JsiCanvasBridge::JsPath2DArc(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
1307 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1308 {
1309 // 5 or 6 parameters: arc(x, y, radius, startAngle, endAngle, anticlockwise?)
1310 if (argc < 5 || argc > 6) {
1311 LOGE("Call Path2D Arc failed, invalid args.");
1312 return runtime->NewUndefined();
1313 }
1314 int32_t id = -1;
1315 auto nodeId = value->GetProperty(runtime, "__id");
1316 if (nodeId && nodeId->IsInt32(runtime)) {
1317 id = nodeId->ToInt32(runtime);
1318 }
1319 if (id < 0) {
1320 return runtime->NewUndefined();
1321 }
1322 auto holderPath = path2Ds_[id];
1323 if (holderPath == nullptr) {
1324 LOGE("Call Path2D Arc failed, holderPath is null.");
1325 return runtime->NewUndefined();
1326 }
1327 bool anticlockwise = false;
1328 if (argc == 6) {
1329 int32_t anti = static_cast<int32_t>(GetJsDoubleVal(runtime, argv[7]));
1330 anticlockwise = (anti == 1);
1331 }
1332 holderPath->Arc(GetJsDoubleVal(runtime, argv[0]), GetJsDoubleVal(runtime, argv[1]),
1333 GetJsDoubleVal(runtime, argv[2]), GetJsDoubleVal(runtime, argv[3]),
1334 GetJsDoubleVal(runtime, argv[4]), anticlockwise);
1335 return runtime->NewUndefined();
1336 }
1337
JsPath2DArcTo(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1338 shared_ptr<JsValue> JsiCanvasBridge::JsPath2DArcTo(const shared_ptr<JsRuntime>& runtime,
1339 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1340 {
1341 // 5 parameters: arcTo(x1, y1, x2, y2, radius)
1342 if (argc != 5) {
1343 LOGE("Call Path2D ArcTo failed, invalid args.");
1344 return runtime->NewUndefined();
1345 }
1346 int32_t id = -1;
1347 auto nodeId = value->GetProperty(runtime, "__id");
1348 if (nodeId && nodeId->IsInt32(runtime)) {
1349 id = nodeId->ToInt32(runtime);
1350 }
1351 if (id < 0) {
1352 return runtime->NewUndefined();
1353 }
1354 auto holderPath = path2Ds_[id];
1355 if (holderPath == nullptr) {
1356 LOGE("Call Path2D ArcTo failed, holderPath is null.");
1357 return runtime->NewUndefined();
1358 }
1359 holderPath->ArcTo(GetJsDoubleVal(runtime, argv[0]), GetJsDoubleVal(runtime, argv[1]),
1360 GetJsDoubleVal(runtime, argv[2]), GetJsDoubleVal(runtime, argv[3]), GetJsDoubleVal(runtime, argv[4]));
1361 return runtime->NewUndefined();
1362 }
1363
JsPath2DQuadraticCurveTo(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1364 shared_ptr<JsValue> JsiCanvasBridge::JsPath2DQuadraticCurveTo(const shared_ptr<JsRuntime>& runtime,
1365 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1366 {
1367 // 4 parameters: quadraticCurveTo(cpx, cpy, x, y)
1368 if (argc != 4) {
1369 LOGE("Call Path2D QuadraticCurveTo failed, invalid args.");
1370 return runtime->NewUndefined();
1371 }
1372 int32_t id = -1;
1373 auto nodeId = value->GetProperty(runtime, "__id");
1374 if (nodeId && nodeId->IsInt32(runtime)) {
1375 id = nodeId->ToInt32(runtime);
1376 }
1377 if (id < 0) {
1378 return runtime->NewUndefined();
1379 }
1380 auto holderPath = path2Ds_[id];
1381 if (holderPath == nullptr) {
1382 LOGE("Call Path2D QuadraticCurveTo failed, holderPath is null.");
1383 return runtime->NewUndefined();
1384 }
1385 holderPath->QuadraticCurveTo(GetJsDoubleVal(runtime, argv[0]), GetJsDoubleVal(runtime, argv[1]),
1386 GetJsDoubleVal(runtime, argv[2]), GetJsDoubleVal(runtime, argv[3]));
1387 return runtime->NewUndefined();
1388 }
1389
JsPath2DBezierCurveTo(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1390 shared_ptr<JsValue> JsiCanvasBridge::JsPath2DBezierCurveTo(const shared_ptr<JsRuntime>& runtime,
1391 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1392 {
1393 // 6 parameters: bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
1394 if (argc != 6) {
1395 LOGE("Call Path2D BezierCurveTo failed, invalid args.");
1396 return runtime->NewUndefined();
1397 }
1398 int32_t id = -1;
1399 auto nodeId = value->GetProperty(runtime, "__id");
1400 if (nodeId && nodeId->IsInt32(runtime)) {
1401 id = nodeId->ToInt32(runtime);
1402 }
1403 if (id < 0) {
1404 return runtime->NewUndefined();
1405 }
1406 auto holderPath = path2Ds_[id];
1407 if (holderPath == nullptr) {
1408 LOGE("Call Path2D BezierCurveTo failed, holderPath is null.");
1409 return runtime->NewUndefined();
1410 }
1411 holderPath->BezierCurveTo(GetJsDoubleVal(runtime, argv[0]), GetJsDoubleVal(runtime, argv[1]),
1412 GetJsDoubleVal(runtime, argv[2]), GetJsDoubleVal(runtime, argv[3]),
1413 GetJsDoubleVal(runtime, argv[4]), GetJsDoubleVal(runtime, argv[5]));
1414 return runtime->NewUndefined();
1415 }
1416
JsPath2DEllipse(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1417 shared_ptr<JsValue> JsiCanvasBridge::JsPath2DEllipse(const shared_ptr<JsRuntime>& runtime,
1418 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1419 {
1420 // 7 or 8 parameters: ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise?)
1421 if (argc < 7 || argc > 8) {
1422 LOGE("Call Path2D Ellipse failed, invalid args.");
1423 return runtime->NewUndefined();
1424 }
1425 int32_t id = -1;
1426 auto nodeId = value->GetProperty(runtime, "__id");
1427 if (nodeId && nodeId->IsInt32(runtime)) {
1428 id = nodeId->ToInt32(runtime);
1429 }
1430 if (id < 0) {
1431 return runtime->NewUndefined();
1432 }
1433 auto holderPath = path2Ds_[id];
1434 if (holderPath == nullptr) {
1435 LOGE("Call Path2D Ellipse failed, holderPath is null.");
1436 return runtime->NewUndefined();
1437 }
1438 bool anticlockwise = false;
1439 if (argc == 8) {
1440 int32_t anti = static_cast<int32_t>(GetJsDoubleVal(runtime, argv[7]));
1441 anticlockwise = (anti == 1);
1442 }
1443 holderPath->Ellipse(GetJsDoubleVal(runtime, argv[0]), GetJsDoubleVal(runtime, argv[1]),
1444 GetJsDoubleVal(runtime, argv[2]), GetJsDoubleVal(runtime, argv[3]),
1445 GetJsDoubleVal(runtime, argv[4]), GetJsDoubleVal(runtime, argv[5]),
1446 GetJsDoubleVal(runtime, argv[6]), anticlockwise);
1447 return runtime->NewUndefined();
1448 }
1449
JsPath2DRect(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1450 shared_ptr<JsValue> JsiCanvasBridge::JsPath2DRect(const shared_ptr<JsRuntime>& runtime,
1451 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1452 {
1453 // 4 parameters: rect(x, y, width, height)
1454 if (argc != 4) {
1455 LOGE("Call Path2D Rect failed, invalid args.");
1456 return runtime->NewUndefined();
1457 }
1458 int32_t id = -1;
1459 auto nodeId = value->GetProperty(runtime, "__id");
1460 if (nodeId && nodeId->IsInt32(runtime)) {
1461 id = nodeId->ToInt32(runtime);
1462 }
1463 if (id < 0) {
1464 return runtime->NewUndefined();
1465 }
1466 auto holderPath = path2Ds_[id];
1467 if (holderPath == nullptr) {
1468 LOGE("Call Path2D Rect failed, holderPath is null.");
1469 return runtime->NewUndefined();
1470 }
1471 holderPath->Rect(GetJsDoubleVal(runtime, argv[0]), GetJsDoubleVal(runtime, argv[1]),
1472 GetJsDoubleVal(runtime, argv[2]), GetJsDoubleVal(runtime, argv[3]));
1473 return runtime->NewUndefined();
1474 }
1475
JsPath2DClosePath(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1476 shared_ptr<JsValue> JsiCanvasBridge::JsPath2DClosePath(const shared_ptr<JsRuntime>& runtime,
1477 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1478 {
1479 int32_t id = -1;
1480 auto nodeId = value->GetProperty(runtime, "__id");
1481 if (nodeId && nodeId->IsInt32(runtime)) {
1482 id = nodeId->ToInt32(runtime);
1483 }
1484 if (id < 0) {
1485 return runtime->NewUndefined();
1486 }
1487 auto holderPath = path2Ds_[id];
1488 if (holderPath == nullptr) {
1489 LOGE("Call Path2D ClosePath failed, holderPath is null.");
1490 return runtime->NewUndefined();
1491 }
1492 holderPath->ClosePath();
1493 return runtime->NewUndefined();
1494 }
1495
JsMakePath2D(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1496 RefPtr<CanvasPath2D> JsiCanvasBridge::JsMakePath2D(const shared_ptr<JsRuntime>& runtime,
1497 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1498 {
1499 if (argc == 1) {
1500 if (argv[0]->IsString(runtime)) {
1501 // Example: ctx.createPath2D("M250 150 L150 350 L350 350 Z")
1502 return AceType::MakeRefPtr<CanvasPath2D>(argv[0]->ToString(runtime));
1503 } else {
1504 auto typeVal = argv[0]->GetProperty(runtime, "__type");
1505 auto type = typeVal->ToString(runtime);
1506 if (type == "path2d") {
1507 // Example: ctx.createPath2D(path1)
1508 return AceType::MakeRefPtr<CanvasPath2D>(GetPath2D(runtime, argv[0]));
1509 }
1510 }
1511 }
1512 // Example: ctx.createPath2D()
1513 return AceType::MakeRefPtr<CanvasPath2D>();
1514 }
1515
GetPath2D(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value)1516 RefPtr<CanvasPath2D> JsiCanvasBridge::GetPath2D(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value)
1517 {
1518 if (!runtime || !value) {
1519 LOGE("runtime or value is null.");
1520 return 0;
1521 }
1522 auto nodeId = value->GetProperty(runtime, "__id");
1523 if (nodeId && nodeId->IsInt32(runtime)) {
1524 auto id = nodeId->ToInt32(runtime);
1525 if (id >= 0) {
1526 return path2Ds_[id];
1527 }
1528 }
1529 return nullptr;
1530 }
1531
JsCreatePattern(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1532 shared_ptr<JsValue> JsiCanvasBridge::JsCreatePattern(const shared_ptr<JsRuntime>& runtime,
1533 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1534 {
1535 if (argc != 2) {
1536 LOGE("argc error, argc = %{private}d", argc);
1537 return runtime->NewUndefined();
1538 }
1539
1540 auto pattern = runtime->NewObject();
1541 pattern->SetProperty(runtime, "__id", runtime->NewInt32(patternCount_));
1542 pattern->SetProperty(runtime, "__type", runtime->NewString("pattern"));
1543 if (!argv[0] || !argv[0]->IsObject(runtime)) {
1544 return runtime->NewUndefined();
1545 }
1546
1547 double width = 0.0;
1548 double height = 0.0;
1549 std::string imageSrc;
1550 auto jsSrc = argv[0]->GetProperty(runtime, DOM_SRC);
1551 if (!jsSrc || !jsSrc->IsString(runtime)) {
1552 ParseDomImage(runtime, argv[0], width, height, imageSrc);
1553 } else {
1554 auto jsWidth = argv[0]->GetProperty(runtime, DOM_WIDTH);
1555 auto jsHeight = argv[0]->GetProperty(runtime, DOM_HEIGHT);
1556 imageSrc = jsSrc->ToString(runtime);
1557 width = jsWidth->ToDouble(runtime);
1558 height = jsHeight->ToDouble(runtime);
1559 }
1560 auto repeat = argv[1]->ToString(runtime);
1561 pattern_[patternCount_].SetImgSrc(imageSrc);
1562 pattern_[patternCount_].SetImageWidth(width);
1563 pattern_[patternCount_].SetImageHeight(height);
1564 pattern_[patternCount_].SetRepetition(repeat);
1565 ++patternCount_;
1566 return pattern;
1567 }
1568
GetPattern(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value)1569 Pattern JsiCanvasBridge::GetPattern(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value)
1570 {
1571 int32_t id = -1;
1572 auto nodeId = value->GetProperty(runtime, "__id");
1573 if (nodeId && nodeId->IsInt32(runtime)) {
1574 id = nodeId->ToInt32(runtime);
1575 }
1576 return id < 0 ? Pattern() : pattern_[id];
1577 }
1578
JsCreateImageData(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1579 shared_ptr<JsValue> JsiCanvasBridge::JsCreateImageData(const shared_ptr<JsRuntime>& runtime,
1580 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1581 {
1582 if (argc != 1 && argc != 2) {
1583 return runtime->NewUndefined();
1584 }
1585
1586 auto imageData = runtime->NewObject();
1587 int32_t width = 0;
1588 int32_t height = 0;
1589
1590 if (argc == 2) {
1591 width = argv[0]->ToInt32(runtime);
1592 height = argv[1]->ToInt32(runtime);
1593 }
1594
1595 if (argc == 1 && argv[0]->IsObject(runtime)) {
1596 auto jsWidth = argv[0]->GetProperty(runtime, DOM_WIDTH);
1597 auto jsHeight = argv[0]->GetProperty(runtime, DOM_HEIGHT);
1598 width = jsWidth->ToInt32(runtime);
1599 height = jsHeight->ToInt32(runtime);
1600 }
1601
1602 auto colorArray = runtime->NewArray();
1603 auto color = runtime->NewInt32(255);
1604 uint32_t count = 0;
1605 for (auto i = 0; i < width; i++) {
1606 for (auto j = 0; j < height; j++) {
1607 colorArray->SetProperty(runtime, runtime->NewInt32(count), color);
1608 colorArray->SetProperty(runtime, runtime->NewInt32(count + 1), color);
1609 colorArray->SetProperty(runtime, runtime->NewInt32(count + 2), color);
1610 colorArray->SetProperty(runtime, runtime->NewInt32(count + 3), color);
1611 count += 4;
1612 }
1613 }
1614 imageData->SetProperty(runtime, DOM_WIDTH, runtime->NewInt32(width));
1615 imageData->SetProperty(runtime, DOM_HEIGHT, runtime->NewInt32(height));
1616 imageData->SetProperty(runtime, "data", colorArray);
1617 return imageData;
1618 }
1619
JsPutImageData(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1620 shared_ptr<JsValue> JsiCanvasBridge::JsPutImageData(const shared_ptr<JsRuntime>& runtime,
1621 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1622 {
1623 if (argc != 3 && argc != 7 && !argv[0]->IsObject(runtime)) {
1624 return runtime->NewUndefined();
1625 }
1626
1627 int32_t width = 0;
1628 int32_t height = 0;
1629 auto jsWidth = argv[0]->GetProperty(runtime, DOM_WIDTH);
1630 auto jsHeight = argv[0]->GetProperty(runtime, DOM_HEIGHT);
1631 width = jsWidth->ToInt32(runtime);
1632 height = jsHeight->ToInt32(runtime);
1633 ImageData imageData;
1634 std::vector<std::string> array;
1635 ParseImageData(runtime, argv, argc, array, imageData);
1636
1637 int64_t num = 0;
1638 for (int32_t i = 0; i < height; ++i) {
1639 for (int32_t j = 0; j < width; ++j) {
1640 if ((i >= imageData.dirtyY) && (i - imageData.dirtyY < imageData.dirtyHeight) && (j >= imageData.dirtyX) &&
1641 (j - imageData.dirtyX < imageData.dirtyWidth)) {
1642 int32_t flag = j + width * i;
1643 if (array.size() > static_cast<uint32_t>(4 * flag + 3)) {
1644 auto red = StringUtils::StringToInt(array[4 * flag]);
1645 auto green = StringUtils::StringToInt(array[4 * flag + 1]);
1646 auto blue = StringUtils::StringToInt(array[4 * flag + 2]);
1647 auto alpha = StringUtils::StringToInt(array[4 * flag + 3]);
1648 if (num < imageData.dirtyWidth * imageData.dirtyHeight) {
1649 imageData.data.emplace_back(Color::FromARGB(alpha, red, green, blue));
1650 }
1651 num++;
1652 }
1653 }
1654 }
1655 }
1656
1657 auto task = [imageData](const RefPtr<CanvasTaskPool>& pool) { pool->PutImageData(imageData); };
1658 PushTaskToPage(runtime, value, task);
1659 return runtime->NewUndefined();
1660 }
1661
ParseImageData(const shared_ptr<JsRuntime> & runtime,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc,std::vector<std::string> & array,ImageData & imageData)1662 void JsiCanvasBridge::ParseImageData(const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1663 int32_t argc, std::vector<std::string>& array, ImageData& imageData)
1664 {
1665 int32_t width = 0;
1666 int32_t height = 0;
1667 auto jsWidth = argv[0]->GetProperty(runtime, DOM_WIDTH);
1668 auto jsHeight = argv[0]->GetProperty(runtime, DOM_HEIGHT);
1669 width = jsWidth->ToInt32(runtime);
1670 height = jsHeight->ToInt32(runtime);
1671
1672 auto jsData = argv[0]->GetProperty(runtime, "data");
1673 auto jsDataStr = jsData->ToString(runtime);
1674 StringUtils::StringSplitter(jsDataStr, ',', array);
1675
1676 imageData.x = argv[1]->ToInt32(runtime);
1677 imageData.y = argv[2]->ToInt32(runtime);
1678 imageData.dirtyWidth = width;
1679 imageData.dirtyHeight = height;
1680
1681 if (argc == 7) {
1682 imageData.dirtyX = argv[3]->ToInt32(runtime);
1683 imageData.dirtyY = argv[4]->ToInt32(runtime);
1684 imageData.dirtyWidth = argv[5]->ToInt32(runtime);
1685 imageData.dirtyHeight = argv[6]->ToInt32(runtime);
1686 }
1687
1688 imageData.dirtyWidth = imageData.dirtyX < 0 ? std::min(imageData.dirtyX + imageData.dirtyWidth, width)
1689 : std::min(width - imageData.dirtyX, imageData.dirtyWidth);
1690 imageData.dirtyHeight = imageData.dirtyY < 0 ? std::min(imageData.dirtyY + imageData.dirtyHeight, height)
1691 : std::min(height - imageData.dirtyY, imageData.dirtyHeight);
1692 }
1693
JsGetImageData(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1694 shared_ptr<JsValue> JsiCanvasBridge::JsGetImageData(const shared_ptr<JsRuntime>& runtime,
1695 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1696 {
1697 if (argc != 4) {
1698 return runtime->NewUndefined();
1699 }
1700 Rect rect = GetJsRectParam(runtime, argc, std::move(argv));
1701 NodeId id = GetCurrentNodeId(runtime, value);
1702 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1703 if (!engine) {
1704 LOGE("JsGetImageData failed. engine is null.");
1705 return runtime->NewUndefined();
1706 }
1707 auto page = engine->GetRunningPage();
1708 if (!page) {
1709 LOGE("JsGetImageData failed. page is null.");
1710 return runtime->NewUndefined();
1711 }
1712 std::unique_ptr<ImageData> data;
1713 auto task = [id, page, &rect, &data]() {
1714 auto canvas = AceType::DynamicCast<DOMCanvas>(page->GetDomDocument()->GetDOMNodeById(id));
1715 if (!canvas) {
1716 return;
1717 }
1718 auto paintChild = AceType::DynamicCast<CustomPaintComponent>(canvas->GetSpecializedComponent());
1719 auto canvasTask = paintChild->GetTaskPool();
1720 if (!canvasTask) {
1721 return;
1722 }
1723 data = canvasTask->GetImageData(rect.Left(), rect.Top(), rect.Width(), rect.Height());
1724 };
1725 auto delegate = engine->GetFrontendDelegate();
1726 if (!delegate) {
1727 LOGE("JsGetImageData failed. delegate is null.");
1728 return runtime->NewUndefined();
1729 }
1730 delegate->PostSyncTaskToPage(task);
1731
1732 auto imageData = runtime->NewObject();
1733 auto colorArray = runtime->NewArray();
1734 imageData->SetProperty(runtime, DOM_WIDTH, runtime->NewInt32(data->dirtyWidth));
1735 imageData->SetProperty(runtime, DOM_HEIGHT, runtime->NewInt32(data->dirtyHeight));
1736 uint32_t count = 0;
1737 // travel data
1738 for (auto i = 0; i < data->dirtyHeight; i++) {
1739 for (auto j = 0; j < data->dirtyWidth; j++) {
1740 // a pixel includes 4 data: red/green/blue/alpha
1741 int32_t idx = i * data->dirtyWidth + j;
1742 auto pixel = data->data[idx];
1743 colorArray->SetProperty(runtime, runtime->NewInt32(count), runtime->NewInt32(pixel.GetRed()));
1744 colorArray->SetProperty(runtime, runtime->NewInt32(count + 1), runtime->NewInt32(pixel.GetGreen()));
1745 colorArray->SetProperty(runtime, runtime->NewInt32(count + 2), runtime->NewInt32(pixel.GetBlue()));
1746 colorArray->SetProperty(runtime, runtime->NewInt32(count + 3), runtime->NewInt32(pixel.GetAlpha()));
1747 count += 4;
1748 }
1749 }
1750 imageData->SetProperty(runtime, "data", colorArray);
1751 return imageData;
1752 }
1753
JsGetPixelMap(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1754 shared_ptr<JsValue> JsiCanvasBridge::JsGetPixelMap(const shared_ptr<JsRuntime>& runtime,
1755 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1756 {
1757 #ifdef PIXEL_MAP_SUPPORTED
1758 // 0 Get input param
1759 if (argc != 4) {
1760 return runtime->NewUndefined();
1761 }
1762 Rect rect = GetJsRectParam(runtime, argc, std::move(argv));
1763 NodeId id = GetCurrentNodeId(runtime, value);
1764 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1765 if (!engine) {
1766 LOGE("JsGetImageData failed. engine is null.");
1767 return runtime->NewUndefined();
1768 }
1769 auto page = engine->GetRunningPage();
1770 if (!page) {
1771 LOGE("JsGetImageData failed. page is null.");
1772 return runtime->NewUndefined();
1773 }
1774 std::unique_ptr<ImageData> imageData;
1775 auto task = [id, page, &rect, &imageData]() {
1776 auto canvas = AceType::DynamicCast<DOMCanvas>(page->GetDomDocument()->GetDOMNodeById(id));
1777 if (!canvas) {
1778 return;
1779 }
1780 auto paintChild = AceType::DynamicCast<CustomPaintComponent>(canvas->GetSpecializedComponent());
1781 auto canvasTask = paintChild->GetTaskPool();
1782 if (!canvasTask) {
1783 return;
1784 }
1785 imageData = canvasTask->GetImageData(rect.Left(), rect.Top(), rect.Width(), rect.Height());
1786 };
1787 auto delegate = engine->GetFrontendDelegate();
1788 if (!delegate) {
1789 LOGE("JsGetImageData failed. delegate is null.");
1790 return runtime->NewUndefined();
1791 }
1792 delegate->PostSyncTaskToPage(task);
1793
1794 // 1 Get data from canvas
1795 uint32_t final_height = static_cast<uint32_t>(imageData->dirtyHeight);
1796 uint32_t final_width = static_cast<uint32_t>(imageData->dirtyWidth);
1797 uint32_t length = final_height * final_width;
1798 uint32_t* data = new uint32_t[length];
1799 for (uint32_t i = 0; i < final_height; i++) {
1800 for (uint32_t j = 0; j < final_width; j++) {
1801 uint32_t idx = i * final_width + j;
1802 Color pixel = imageData->data[idx];
1803 data[idx] = pixel.GetValue();
1804 }
1805 }
1806
1807 // 2 Create pixelmap
1808 OHOS::Media::InitializationOptions options;
1809 options.alphaType = OHOS::Media::AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
1810 options.pixelFormat = OHOS::Media::PixelFormat::RGBA_8888;
1811 options.scaleMode = OHOS::Media::ScaleMode::CENTER_CROP;
1812 options.size.width = static_cast<int32_t>(final_width);
1813 options.size.height = static_cast<int32_t>(final_height);
1814 options.editable = true;
1815 std::unique_ptr<OHOS::Media::PixelMap> pixelmap = OHOS::Media::PixelMap::Create(data, length, options);
1816 delete[] data;
1817 if (pixelmap == nullptr) {
1818 LOGE(" pixelmap is null.");
1819 return runtime->NewUndefined();
1820 }
1821
1822 // 3 pixelmap to NapiValue
1823 auto nativeEngine = static_cast<ArkNativeEngine*>(engine->GetNativeEngine());
1824 if (!nativeEngine) {
1825 LOGE("NativeEngine is null");
1826 return runtime->NewUndefined();
1827 }
1828 napi_env env = reinterpret_cast<napi_env>(nativeEngine);
1829 std::shared_ptr<OHOS::Media::PixelMap> sharedPixelmap(pixelmap.release());
1830 napi_value napiValue = OHOS::Media::PixelMapNapi::CreatePixelMap(env, sharedPixelmap);
1831
1832 if (!napiValue) {
1833 LOGE("napiValue is null");
1834 return runtime->NewUndefined();
1835 }
1836
1837 auto arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
1838 if (!arkRuntime) {
1839 LOGE("arkRuntime is null");
1840 return runtime->NewUndefined();
1841 }
1842 auto jsValue = std::make_shared<ArkJSValue>(arkRuntime, NapiValueToLocalValue(napiValue));
1843 if (!jsValue) {
1844 LOGE("jsValue is null");
1845 return runtime->NewUndefined();
1846 }
1847
1848 return jsValue;
1849 #else
1850 LOGW("[Engine Log] The function 'getPixelMap' is not supported on the current platform.");
1851 return runtime->NewUndefined();
1852 #endif
1853 }
1854
JsGetJsonData(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1855 shared_ptr<JsValue> JsiCanvasBridge::JsGetJsonData(const shared_ptr<JsRuntime>& runtime,
1856 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1857 {
1858 if (argc != 1) {
1859 return runtime->NewUndefined();
1860 }
1861 NodeId id = GetCurrentNodeId(runtime, value);
1862 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1863 if (!engine) {
1864 LOGE("JsGetJsonData failed. engine is null.");
1865 return runtime->NewUndefined();
1866 }
1867 auto page = engine->GetRunningPage();
1868 if (!page) {
1869 LOGE("JsGetJsonData failed. page is null.");
1870 return runtime->NewUndefined();
1871 }
1872 std::string path = argv[0]->ToString(runtime);
1873 std::string jsonData;
1874 auto task = [id, page, path, &jsonData]() {
1875 auto canvas = AceType::DynamicCast<DOMCanvas>(page->GetDomDocument()->GetDOMNodeById(id));
1876 if (!canvas) {
1877 return;
1878 }
1879 auto paintChild = AceType::DynamicCast<CustomPaintComponent>(canvas->GetSpecializedComponent());
1880 auto canvasTask = paintChild->GetTaskPool();
1881 if (!canvasTask) {
1882 return;
1883 }
1884 jsonData = canvasTask->GetJsonData(path);
1885 };
1886 auto delegate = engine->GetFrontendDelegate();
1887 if (!delegate) {
1888 LOGE("JsGetJsonData failed. delegate is null.");
1889 return runtime->NewUndefined();
1890 }
1891 delegate->PostSyncTaskToPage(task);
1892
1893 return runtime->NewString(jsonData.c_str());
1894 }
1895
JsTransferFromImageBitmap(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1896 shared_ptr<JsValue> JsiCanvasBridge::JsTransferFromImageBitmap(const shared_ptr<JsRuntime>& runtime,
1897 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1898 {
1899 if (argc != 1) {
1900 return runtime->NewUndefined();
1901 }
1902
1903 int32_t bridgeId = 0;
1904 auto id = argv[0]->GetProperty(runtime, "__bridgeId");
1905 if (id && id->IsInt32(runtime)) {
1906 bridgeId = id->ToInt32(runtime);
1907 }
1908 bridgeId = bridgeId < 0 ? 0 : bridgeId;
1909
1910 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1911 if (!engine) {
1912 return runtime->NewUndefined();
1913 }
1914 auto page = engine->GetRunningPage();
1915 if (page) {
1916 RefPtr<JsiOffscreenCanvasBridge> bridge = AceType::DynamicCast<JsiOffscreenCanvasBridge>(
1917 page->GetOffscreenCanvasBridgeById(bridgeId));
1918 if (bridge) {
1919 auto offscreenCanvas = bridge->GetOffscreenCanvas();
1920 auto task = [offscreenCanvas](const RefPtr<CanvasTaskPool>& pool) {
1921 pool->TransferFromImageBitmap(offscreenCanvas);
1922 };
1923 PushTaskToPage(runtime, value, task);
1924 }
1925 }
1926 return runtime->NewUndefined();
1927 }
1928
JsDrawBitmapMesh(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1929 shared_ptr<JsValue> JsiCanvasBridge::JsDrawBitmapMesh(const shared_ptr<JsRuntime>& runtime,
1930 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1931 {
1932 if (argc != 4) {
1933 return runtime->NewUndefined();
1934 }
1935 int32_t bridgeId = 0;
1936 auto id = argv[0]->GetProperty(runtime, "__bridgeId");
1937 if (id && id->IsInt32(runtime)) {
1938 bridgeId = id->ToInt32(runtime);
1939 }
1940 bridgeId = bridgeId < 0 ? 0 : bridgeId;
1941 auto mesh = GetJsDashValue(runtime, argv[1]);
1942 int32_t column = argv[2]->ToInt32(runtime);
1943 int32_t row = argv[3]->ToInt32(runtime);
1944
1945 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1946 if (!engine) {
1947 return runtime->NewUndefined();
1948 }
1949 auto page = engine->GetRunningPage();
1950 if (page) {
1951 RefPtr<JsiOffscreenCanvasBridge> bridge = AceType::DynamicCast<JsiOffscreenCanvasBridge>(
1952 page->GetOffscreenCanvasBridgeById(bridgeId));
1953 if (bridge) {
1954 auto offscreenCanvas = bridge->GetOffscreenCanvas();
1955 auto task = [offscreenCanvas, mesh, column, row](const RefPtr<CanvasTaskPool>& pool) {
1956 pool->DrawBitmapMesh(offscreenCanvas, mesh, column, row);
1957 };
1958 PushTaskToPage(runtime, value, task);
1959 }
1960 }
1961 return runtime->NewUndefined();
1962 }
1963
JsFillStyleGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1964 shared_ptr<JsValue> JsiCanvasBridge::JsFillStyleGetter(const shared_ptr<JsRuntime>& runtime,
1965 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1966 {
1967 return value->GetProperty(runtime, "__fillStyle");
1968 }
1969
JsFillStyleSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1970 shared_ptr<JsValue> JsiCanvasBridge::JsFillStyleSetter(const shared_ptr<JsRuntime>& runtime,
1971 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1972 {
1973 if (argv.empty() || argc == 0) {
1974 return runtime->NewUndefined();
1975 }
1976 auto proto = argv[0];
1977 if (!proto) {
1978 return runtime->NewUndefined();
1979 }
1980 if (proto->IsString(runtime)) {
1981 auto colorStr = proto->ToString(runtime);
1982 auto color = Color::FromString(colorStr);
1983 auto task = [color](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateFillColor(color); };
1984 PushTaskToPage(runtime, value, task);
1985 } else {
1986 auto typeVal = proto->GetProperty(runtime, "__type");
1987 auto type = typeVal->ToString(runtime);
1988 if (type == "gradient") {
1989 auto gradient = GetGradient(runtime, proto);
1990 auto task = [gradient](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateFillGradient(gradient); };
1991 PushTaskToPage(runtime, value, task);
1992 } else if (type == "pattern") {
1993 auto pattern = GetPattern(runtime, proto);
1994 auto task = [pattern](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateFillPattern(pattern); };
1995 PushTaskToPage(runtime, value, task);
1996 } else {
1997 LOGW("No such type for fill style.");
1998 }
1999 }
2000 value->SetProperty(runtime, "__fillStyle", proto);
2001 return runtime->NewUndefined();
2002 }
2003
JsStrokeStyleGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2004 shared_ptr<JsValue> JsiCanvasBridge::JsStrokeStyleGetter(const shared_ptr<JsRuntime>& runtime,
2005 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2006 {
2007 return value->GetProperty(runtime, "__strokeStyle");
2008 }
2009
JsStrokeStyleSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2010 shared_ptr<JsValue> JsiCanvasBridge::JsStrokeStyleSetter(const shared_ptr<JsRuntime>& runtime,
2011 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2012 {
2013 if (argv.empty() || argc == 0) {
2014 return runtime->NewUndefined();
2015 }
2016 auto proto = argv[0];
2017 if (!proto) {
2018 return runtime->NewUndefined();
2019 }
2020 if (proto->IsString(runtime)) {
2021 auto colorStr = proto->ToString(runtime);
2022 auto color = Color::FromString(colorStr);
2023 auto task = [color](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateStrokeColor(color); };
2024 PushTaskToPage(runtime, value, task);
2025 } else {
2026 auto typeVal = proto->GetProperty(runtime, "__type");
2027 auto type = typeVal->ToString(runtime);
2028 if (type == "gradient") {
2029 auto gradient = GetGradient(runtime, proto);
2030 auto task = [gradient](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateStrokeGradient(gradient); };
2031 PushTaskToPage(runtime, value, task);
2032 } else if (type == "pattern") {
2033 auto pattern = GetPattern(runtime, proto);
2034 auto task = [pattern](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateStrokePattern(pattern); };
2035 PushTaskToPage(runtime, value, task);
2036 } else {
2037 LOGW("No such type for stroke style.");
2038 }
2039 }
2040 value->SetProperty(runtime, "__strokeStyle", proto);
2041 return runtime->NewUndefined();
2042 }
2043
JsLineCapGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2044 shared_ptr<JsValue> JsiCanvasBridge::JsLineCapGetter(const shared_ptr<JsRuntime>& runtime,
2045 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2046 {
2047 return value->GetProperty(runtime, "__lineCap");
2048 }
2049
JsLineCapSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2050 shared_ptr<JsValue> JsiCanvasBridge::JsLineCapSetter(const shared_ptr<JsRuntime>& runtime,
2051 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2052 {
2053 if (argv.empty() || argc == 0) {
2054 return runtime->NewUndefined();
2055 }
2056 auto proto = argv[0];
2057 if (!proto) {
2058 return runtime->NewUndefined();
2059 }
2060 auto capStr = proto->ToString(runtime);
2061 static const LinearMapNode<LineCapStyle> lineCapTable[] = {
2062 { "butt", LineCapStyle::BUTT },
2063 { "round", LineCapStyle::ROUND },
2064 { "square", LineCapStyle::SQUARE },
2065 };
2066 auto lineCap = ConvertStrToEnum(capStr.c_str(), lineCapTable, ArraySize(lineCapTable), LineCapStyle::BUTT);
2067 auto task = [lineCap](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateLineCap(lineCap); };
2068 PushTaskToPage(runtime, value, task);
2069 value->SetProperty(runtime, "__lineCap", proto);
2070 return runtime->NewUndefined();
2071 }
2072
JsLineJoinGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2073 shared_ptr<JsValue> JsiCanvasBridge::JsLineJoinGetter(const shared_ptr<JsRuntime>& runtime,
2074 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2075 {
2076 return value->GetProperty(runtime, "__lineJoin");
2077 }
2078
JsLineJoinSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2079 shared_ptr<JsValue> JsiCanvasBridge::JsLineJoinSetter(const shared_ptr<JsRuntime>& runtime,
2080 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2081 {
2082 if (argv.empty() || argc == 0) {
2083 return runtime->NewUndefined();
2084 }
2085 auto proto = argv[0];
2086 if (!proto) {
2087 return runtime->NewUndefined();
2088 }
2089 auto joinStr = proto->ToString(runtime);
2090 static const LinearMapNode<LineJoinStyle> lineJoinTable[3] = {
2091 { "bevel", LineJoinStyle::BEVEL },
2092 { "miter", LineJoinStyle::MITER },
2093 { "round", LineJoinStyle::ROUND },
2094 };
2095 auto lineJoin = ConvertStrToEnum(joinStr.c_str(), lineJoinTable, ArraySize(lineJoinTable), LineJoinStyle::MITER);
2096 auto task = [lineJoin](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateLineJoin(lineJoin); };
2097 PushTaskToPage(runtime, value, task);
2098 value->SetProperty(runtime, "__lineJoin", proto);
2099 return runtime->NewUndefined();
2100 }
2101
JsMiterLimitGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2102 shared_ptr<JsValue> JsiCanvasBridge::JsMiterLimitGetter(const shared_ptr<JsRuntime>& runtime,
2103 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2104 {
2105 return value->GetProperty(runtime, "__miterLimit");
2106 }
2107
JsMiterLimitSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2108 shared_ptr<JsValue> JsiCanvasBridge::JsMiterLimitSetter(const shared_ptr<JsRuntime>& runtime,
2109 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2110 {
2111 if (argv.empty() || argc == 0) {
2112 return runtime->NewUndefined();
2113 }
2114 auto proto = argv[0];
2115 if (!proto) {
2116 return runtime->NewUndefined();
2117 }
2118 double limit = GetJsDoubleVal(runtime, proto);
2119 auto task = [limit](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateMiterLimit(limit); };
2120 PushTaskToPage(runtime, value, task);
2121 value->SetProperty(runtime, "__miterLimit", proto);
2122 return runtime->NewUndefined();
2123 }
2124
JsLineWidthGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2125 shared_ptr<JsValue> JsiCanvasBridge::JsLineWidthGetter(const shared_ptr<JsRuntime>& runtime,
2126 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2127 {
2128 return value->GetProperty(runtime, "__lineWidth");
2129 }
2130
JsLineWidthSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2131 shared_ptr<JsValue> JsiCanvasBridge::JsLineWidthSetter(const shared_ptr<JsRuntime>& runtime,
2132 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2133 {
2134 if (argv.empty() || argc == 0) {
2135 return runtime->NewUndefined();
2136 }
2137 auto proto = argv[0];
2138 if (!proto) {
2139 return runtime->NewUndefined();
2140 }
2141 double lineWidth = GetJsDoubleVal(runtime, proto);
2142 auto task = [lineWidth](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateLineWidth(lineWidth); };
2143 PushTaskToPage(runtime, value, task);
2144 value->SetProperty(runtime, "__lineWidth", proto);
2145 return runtime->NewUndefined();
2146 }
2147
JsTextAlignGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2148 shared_ptr<JsValue> JsiCanvasBridge::JsTextAlignGetter(const shared_ptr<JsRuntime>& runtime,
2149 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2150 {
2151 return value->GetProperty(runtime, "__textAlign");
2152 }
2153
JsTextAlignSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2154 shared_ptr<JsValue> JsiCanvasBridge::JsTextAlignSetter(const shared_ptr<JsRuntime>& runtime,
2155 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2156 {
2157 if (argv.empty() || argc == 0) {
2158 return runtime->NewUndefined();
2159 }
2160 auto proto = argv[0];
2161 if (!proto) {
2162 return runtime->NewUndefined();
2163 }
2164 auto alignStr = proto->ToString(runtime);
2165 auto align = ConvertStrToTextAlign(alignStr);
2166 auto task = [align](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateTextAlign(align); };
2167 PushTaskToPage(runtime, value, task);
2168 value->SetProperty(runtime, "__textAlign", proto);
2169 return runtime->NewUndefined();
2170 }
2171
JsTextBaselineGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2172 shared_ptr<JsValue> JsiCanvasBridge::JsTextBaselineGetter(const shared_ptr<JsRuntime>& runtime,
2173 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2174 {
2175 return value->GetProperty(runtime, "__textBaseline");
2176 }
2177
JsTextBaselineSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2178 shared_ptr<JsValue> JsiCanvasBridge::JsTextBaselineSetter(const shared_ptr<JsRuntime>& runtime,
2179 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2180 {
2181 if (argv.empty() || argc == 0) {
2182 return runtime->NewUndefined();
2183 }
2184 auto proto = argv[0];
2185 if (!proto) {
2186 return runtime->NewUndefined();
2187 }
2188 auto baselineStr = proto->ToString(runtime);
2189 auto baseline =
2190 ConvertStrToEnum(baselineStr.c_str(), BASELINE_TABLE, ArraySize(BASELINE_TABLE), TextBaseline::ALPHABETIC);
2191 auto task = [baseline](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateTextBaseline(baseline); };
2192 PushTaskToPage(runtime, value, task);
2193 value->SetProperty(runtime, "__textBaseline", proto);
2194 return runtime->NewUndefined();
2195 }
2196
JsFontGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2197 shared_ptr<JsValue> JsiCanvasBridge::JsFontGetter(const shared_ptr<JsRuntime>& runtime,
2198 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2199 {
2200 return value->GetProperty(runtime, "__font");
2201 }
2202
JsFontSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2203 shared_ptr<JsValue> JsiCanvasBridge::JsFontSetter(const shared_ptr<JsRuntime>& runtime,
2204 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2205 {
2206 if (argv.empty() || argc == 0) {
2207 return runtime->NewUndefined();
2208 }
2209 auto proto = argv[0];
2210 if (!proto) {
2211 return runtime->NewUndefined();
2212 }
2213 auto fontStr = proto->ToString(runtime);
2214 std::vector<std::string> fontProps;
2215 StringUtils::StringSplitter(fontStr, ' ', fontProps);
2216 for (const auto& fontProp : fontProps) {
2217 if (FONT_STYLES.find(fontProp) != FONT_STYLES.end()) {
2218 auto fontStyle = ConvertStrToFontStyle(fontProp);
2219 auto task = [fontStyle](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateFontStyle(fontStyle); };
2220 PushTaskToPage(runtime, value, task);
2221 } else if (FONT_WEIGHTS.find(fontProp) != FONT_WEIGHTS.end()) {
2222 auto weight = ConvertStrToFontWeight(fontProp);
2223 auto task = [weight](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateFontWeight(weight); };
2224 PushTaskToPage(runtime, value, task);
2225 } else if (FONT_FAMILIES.find(fontProp) != FONT_FAMILIES.end()) {
2226 auto families = ConvertStrToFontFamilies(fontProp);
2227 auto task = [families](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateFontFamilies(families); };
2228 PushTaskToPage(runtime, value, task);
2229 } else if (fontProp.find("px") != std::string::npos) {
2230 std::string fontSize = fontProp.substr(0, fontProp.size() - 2);
2231 auto size = Dimension(StringToDouble(fontProp));
2232 auto task = [size](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateFontSize(size); };
2233 PushTaskToPage(runtime, value, task);
2234 } else {
2235 LOGW("parse text error");
2236 }
2237 }
2238 value->SetProperty(runtime, "__font", proto);
2239 return runtime->NewUndefined();
2240 }
2241
JsAlphaGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2242 shared_ptr<JsValue> JsiCanvasBridge::JsAlphaGetter(const shared_ptr<JsRuntime>& runtime,
2243 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2244 {
2245 return value->GetProperty(runtime, "__globalAlpha");
2246 }
2247
JsAlphaSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2248 shared_ptr<JsValue> JsiCanvasBridge::JsAlphaSetter(const shared_ptr<JsRuntime>& runtime,
2249 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2250 {
2251 if (argv.empty() || argc == 0) {
2252 return runtime->NewUndefined();
2253 }
2254 auto proto = argv[0];
2255 if (!proto) {
2256 return runtime->NewUndefined();
2257 }
2258 double alpha = GetJsDoubleVal(runtime, proto);
2259 auto task = [alpha](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateGlobalAlpha(alpha); };
2260 PushTaskToPage(runtime, value, task);
2261 value->SetProperty(runtime, "__globalAlpha", proto);
2262 return runtime->NewUndefined();
2263 }
2264
JsCompositeOperationGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2265 shared_ptr<JsValue> JsiCanvasBridge::JsCompositeOperationGetter(const shared_ptr<JsRuntime>& runtime,
2266 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2267 {
2268 return value->GetProperty(runtime, "__globalCompositeOperation");
2269 }
2270
JsCompositeOperationSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2271 shared_ptr<JsValue> JsiCanvasBridge::JsCompositeOperationSetter(const shared_ptr<JsRuntime>& runtime,
2272 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2273 {
2274 if (argv.empty() || argc == 0) {
2275 return runtime->NewUndefined();
2276 }
2277 auto proto = argv[0];
2278 if (!proto) {
2279 return runtime->NewUndefined();
2280 }
2281 auto typeStr = proto->ToString(runtime);
2282 // this map must be sorted by key.
2283 static const LinearMapNode<CompositeOperation> compositeOperationTable[] = {
2284 { "copy", CompositeOperation::COPY },
2285 { "destination-atop", CompositeOperation::DESTINATION_ATOP },
2286 { "destination-in", CompositeOperation::DESTINATION_IN },
2287 { "destination-out", CompositeOperation::DESTINATION_OUT },
2288 { "destination-over", CompositeOperation::DESTINATION_OVER },
2289 { "lighter", CompositeOperation::LIGHTER },
2290 { "source-atop", CompositeOperation::SOURCE_ATOP },
2291 { "source-in", CompositeOperation::SOURCE_IN },
2292 { "source-out", CompositeOperation::SOURCE_OUT },
2293 { "source-over", CompositeOperation::SOURCE_OVER },
2294 { "xor", CompositeOperation::XOR },
2295 };
2296 auto type = ConvertStrToEnum(
2297 typeStr.c_str(), compositeOperationTable, ArraySize(compositeOperationTable), CompositeOperation::SOURCE_OVER);
2298 auto task = [type](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateCompositeOperation(type); };
2299 PushTaskToPage(runtime, value, task);
2300 value->SetProperty(runtime, "__globalCompositeOperation", proto);
2301 return runtime->NewUndefined();
2302 }
2303
JsLineDashOffsetGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2304 shared_ptr<JsValue> JsiCanvasBridge::JsLineDashOffsetGetter(const shared_ptr<JsRuntime>& runtime,
2305 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2306 {
2307 return value->GetProperty(runtime, "__lineDash");
2308 }
2309
JsLineDashOffsetSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2310 shared_ptr<JsValue> JsiCanvasBridge::JsLineDashOffsetSetter(const shared_ptr<JsRuntime>& runtime,
2311 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2312 {
2313 if (argv.empty() || argc == 0) {
2314 return runtime->NewUndefined();
2315 }
2316 auto proto = argv[0];
2317 if (!proto) {
2318 return runtime->NewUndefined();
2319 }
2320 double dashoffset = GetJsDoubleVal(runtime, proto);
2321 auto task = [dashoffset](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateLineDashOffset(dashoffset); };
2322 PushTaskToPage(runtime, value, task);
2323 value->SetProperty(runtime, "__lineDash", proto);
2324 return runtime->NewUndefined();
2325 }
2326
JsShadowBlurGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2327 shared_ptr<JsValue> JsiCanvasBridge::JsShadowBlurGetter(const shared_ptr<JsRuntime>& runtime,
2328 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2329 {
2330 return value->GetProperty(runtime, "__shadowBlur");
2331 }
2332
JsShadowBlurSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2333 shared_ptr<JsValue> JsiCanvasBridge::JsShadowBlurSetter(const shared_ptr<JsRuntime>& runtime,
2334 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2335 {
2336 if (argv.empty() || argc == 0) {
2337 return runtime->NewUndefined();
2338 }
2339 auto proto = argv[0];
2340 if (!proto) {
2341 return runtime->NewUndefined();
2342 }
2343 double blur = GetJsDoubleVal(runtime, proto);
2344 auto task = [blur](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateShadowBlur(blur); };
2345 PushTaskToPage(runtime, value, task);
2346 value->SetProperty(runtime, "__shadowBlur", proto);
2347 return runtime->NewUndefined();
2348 }
2349
JsShadowColorGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2350 shared_ptr<JsValue> JsiCanvasBridge::JsShadowColorGetter(const shared_ptr<JsRuntime>& runtime,
2351 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2352 {
2353 return value->GetProperty(runtime, "__shadowColor");
2354 }
2355
JsShadowColorSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2356 shared_ptr<JsValue> JsiCanvasBridge::JsShadowColorSetter(const shared_ptr<JsRuntime>& runtime,
2357 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2358 {
2359 if (argv.empty() || argc == 0) {
2360 return runtime->NewUndefined();
2361 }
2362 auto proto = argv[0];
2363 if (!proto) {
2364 return runtime->NewUndefined();
2365 }
2366 auto colorStr = proto->ToString(runtime);
2367 auto color = Color::FromString(colorStr);
2368 auto task = [color](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateShadowColor(color); };
2369 PushTaskToPage(runtime, value, task);
2370 value->SetProperty(runtime, "__shadowColor", proto);
2371 return runtime->NewUndefined();
2372 }
2373
JsShadowOffsetXGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2374 shared_ptr<JsValue> JsiCanvasBridge::JsShadowOffsetXGetter(const shared_ptr<JsRuntime>& runtime,
2375 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2376 {
2377 return value->GetProperty(runtime, "__shadowOffsetX");
2378 }
2379
JsShadowOffsetXSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2380 shared_ptr<JsValue> JsiCanvasBridge::JsShadowOffsetXSetter(const shared_ptr<JsRuntime>& runtime,
2381 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2382 {
2383 if (argv.empty() || argc == 0) {
2384 return runtime->NewUndefined();
2385 }
2386 auto proto = argv[0];
2387 if (!proto) {
2388 return runtime->NewUndefined();
2389 }
2390 double offsetX = GetJsDoubleVal(runtime, proto);
2391 auto task = [offsetX](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateShadowOffsetX(offsetX); };
2392 PushTaskToPage(runtime, value, task);
2393 value->SetProperty(runtime, "__shadowOffsetX", proto);
2394 return runtime->NewUndefined();
2395 }
2396
JsShadowOffsetYGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2397 shared_ptr<JsValue> JsiCanvasBridge::JsShadowOffsetYGetter(const shared_ptr<JsRuntime>& runtime,
2398 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2399 {
2400 return value->GetProperty(runtime, "__shadowOffsetY");
2401 }
2402
JsShadowOffsetYSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2403 shared_ptr<JsValue> JsiCanvasBridge::JsShadowOffsetYSetter(const shared_ptr<JsRuntime>& runtime,
2404 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2405 {
2406 if (argv.empty() || argc == 0) {
2407 return runtime->NewUndefined();
2408 }
2409 auto proto = argv[0];
2410 if (!proto) {
2411 return runtime->NewUndefined();
2412 }
2413 double offsetY = GetJsDoubleVal(runtime, proto);
2414 auto task = [offsetY](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateShadowOffsetY(offsetY); };
2415 PushTaskToPage(runtime, value, task);
2416 value->SetProperty(runtime, "__shadowOffsetY", proto);
2417 return runtime->NewUndefined();
2418 }
2419
JsSmoothingEnabledGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2420 shared_ptr<JsValue> JsiCanvasBridge::JsSmoothingEnabledGetter(const shared_ptr<JsRuntime>& runtime,
2421 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2422 {
2423 return value->GetProperty(runtime, "__imageSmoothingEnabled");
2424 }
2425
JsSmoothingEnabledSetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2426 shared_ptr<JsValue> JsiCanvasBridge::JsSmoothingEnabledSetter(const shared_ptr<JsRuntime>& runtime,
2427 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2428 {
2429 if (argv.empty() || argc == 0) {
2430 return runtime->NewUndefined();
2431 }
2432 auto proto = argv[0];
2433 if (!proto || !proto->IsBoolean(runtime)) {
2434 return runtime->NewUndefined();
2435 }
2436 auto enabled = proto->ToBoolean(runtime);
2437 auto task = [enabled](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateSmoothingEnabled(enabled); };
2438 PushTaskToPage(runtime, value, task);
2439 value->SetProperty(runtime, "__imageSmoothingEnabled", proto);
2440 return runtime->NewUndefined();
2441 }
2442
JsSmoothingQualityGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2443 shared_ptr<JsValue> JsiCanvasBridge::JsSmoothingQualityGetter(const shared_ptr<JsRuntime>& runtime,
2444 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2445 {
2446 return value->GetProperty(runtime, "__imageSmoothingQuality");
2447 }
2448
JsSmoothingQualitySetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2449 shared_ptr<JsValue> JsiCanvasBridge::JsSmoothingQualitySetter(const shared_ptr<JsRuntime>& runtime,
2450 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2451 {
2452 if (argv.empty() || argc == 0) {
2453 return runtime->NewUndefined();
2454 }
2455 auto proto = argv[0];
2456 if (!proto || !proto->IsString(runtime)) {
2457 return runtime->NewUndefined();
2458 }
2459 const std::string& quality = proto->ToString(runtime);
2460 if (quality.empty() || QUALITY_TYPE.find(quality) == QUALITY_TYPE.end()) {
2461 return runtime->NewUndefined();
2462 }
2463 auto task = [quality](const RefPtr<CanvasTaskPool>& pool) { pool->UpdateSmoothingQuality(quality); };
2464 PushTaskToPage(runtime, value, task);
2465 value->SetProperty(runtime, "__imageSmoothingQuality", proto);
2466 return runtime->NewUndefined();
2467 }
2468
JsWidthGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2469 shared_ptr<JsValue> JsiCanvasBridge::JsWidthGetter(const shared_ptr<JsRuntime>& runtime,
2470 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2471 {
2472 NodeId id = GetCurrentNodeId(runtime, value);
2473 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
2474 if (!engine) {
2475 return runtime->NewUndefined();
2476 }
2477 auto page = engine->GetRunningPage();
2478 if (!page) {
2479 return runtime->NewUndefined();
2480 }
2481
2482 double width = 0.0;
2483 auto task = [id, page, &width]() {
2484 auto canvas = AceType::DynamicCast<DOMCanvas>(page->GetDomDocument()->GetDOMNodeById(id));
2485 if (!canvas) {
2486 return;
2487 }
2488 auto paintChild = AceType::DynamicCast<CustomPaintComponent>(canvas->GetSpecializedComponent());
2489 if (!paintChild) {
2490 return;
2491 }
2492 auto canvasTask = paintChild->GetTaskPool();
2493 if (!canvasTask) {
2494 return;
2495 }
2496 width = canvasTask->GetWidth();
2497 };
2498 auto delegate = engine->GetFrontendDelegate();
2499 if (!delegate) {
2500 return runtime->NewUndefined();
2501 }
2502 delegate->PostSyncTaskToPage(task);
2503
2504 return runtime->NewNumber(width);
2505 }
2506
JsHeightGetter(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2507 shared_ptr<JsValue> JsiCanvasBridge::JsHeightGetter(const shared_ptr<JsRuntime>& runtime,
2508 const shared_ptr<JsValue>& value, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2509 {
2510 NodeId id = GetCurrentNodeId(runtime, value);
2511 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
2512 if (!engine) {
2513 return runtime->NewUndefined();
2514 }
2515 auto page = engine->GetRunningPage();
2516 if (!page) {
2517 return runtime->NewUndefined();
2518 }
2519
2520 double height = 0.0;
2521 auto task = [id, page, &height]() {
2522 auto canvas = AceType::DynamicCast<DOMCanvas>(page->GetDomDocument()->GetDOMNodeById(id));
2523 if (!canvas) {
2524 return;
2525 }
2526 auto paintChild = AceType::DynamicCast<CustomPaintComponent>(canvas->GetSpecializedComponent());
2527 if (!paintChild) {
2528 return;
2529 }
2530 auto canvasTask = paintChild->GetTaskPool();
2531 if (!canvasTask) {
2532 return;
2533 }
2534 height = canvasTask->GetHeight();
2535 };
2536 auto delegate = engine->GetFrontendDelegate();
2537 if (!delegate) {
2538 return runtime->NewUndefined();
2539 }
2540 delegate->PostSyncTaskToPage(task);
2541
2542 return runtime->NewNumber(height);
2543 }
2544
2545 } // namespace OHOS::Ace::Framework
2546