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