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