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