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