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