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