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