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