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