• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/quickjs/chart_bridge.h"
17 
18 #include "base/utils/linear_map.h"
19 #include "base/utils/utils.h"
20 #include "frameworks/bridge/common/utils/utils.h"
21 
22 namespace OHOS::Ace::Framework {
23 
24 namespace {
25 
26 constexpr int32_t VALID_ARRAY_LENGTH = 2;
27 constexpr uint32_t ARRAY_X_VALUE = 0;
28 constexpr uint32_t ARRAY_Y_VALUE = 1;
29 
GetAttrOptionsAxis(JSContext * ctx,JSValueConst valObject,AxisOption & axisOption)30 void GetAttrOptionsAxis(JSContext* ctx, JSValueConst valObject, AxisOption& axisOption)
31 {
32     JSPropertyEnum* pTab = nullptr;
33     uint32_t len = 0;
34     if (!CheckAndGetJsProperty(ctx, valObject, &pTab, &len)) {
35         return;
36     }
37     JS_GetOwnPropertyNames(ctx, &pTab, &len, valObject, JS_GPN_STRING_MASK);
38     for (uint32_t i = 0; i < len; i++) {
39         const char* key = JS_AtomToCString(ctx, pTab[i].atom);
40         if (key == nullptr) {
41             JS_FreeAtom(ctx, pTab[i].atom);
42             LOGW("key is null. Ignoring!");
43             continue;
44         }
45         JSValue val = JS_GetProperty(ctx, valObject, pTab[i].atom);
46         if (JS_IsNumber(val) || JS_IsBool(val) || JS_IsString(val)) {
47             // must sorted by key.
48             static const LinearMapNode<void (*)(const char*, AxisOption&)> chartOptionsAxisMap[] = {
49                 { "axisTick",
50                     [](const char* valStr, AxisOption& axis) {
51                         axis.tickNumber = StringUtils::StringToInt(valStr);
52                     } },
53                 { "color",
54                     [](const char* valStr, AxisOption& axis) {
55                         axis.color = Color::FromString(valStr);
56                     } },
57                 { "display",
58                     [](const char* valStr, AxisOption& axis) {
59                         axis.display = StringToBool(valStr);
60                     } },
61                 { "max",
62                     [](const char* valStr, AxisOption& axis) {
63                         axis.max = StringToDouble(valStr);
64                     } },
65                 { "min",
66                     [](const char* valStr, AxisOption& axis) {
67                         axis.min = StringToDouble(valStr);
68                     } },
69             };
70             auto iter = BinarySearchFindIndex(chartOptionsAxisMap, ArraySize(chartOptionsAxisMap), key);
71             if (iter != -1) {
72                 ScopedString styleVal(ctx, val);
73                 chartOptionsAxisMap[iter].value(styleVal.get(), axisOption);
74             } else {
75                 LOGD("key : %{public}s unsupported. Ignoring!", key);
76             }
77         } else {
78             LOGD("key : %{public}s, value of unsupported type. Ignoring!", key);
79         }
80         JS_FreeAtom(ctx, pTab[i].atom);
81         JS_FreeCString(ctx, key);
82         JS_FreeValue(ctx, val);
83     }
84     js_free(ctx, pTab);
85 }
86 
GetAttrOptionsSeriesPoint(JSContext * ctx,JSValueConst valObject,PointInfo & pointInfo)87 void GetAttrOptionsSeriesPoint(JSContext* ctx, JSValueConst valObject, PointInfo& pointInfo)
88 {
89     JSPropertyEnum* pTab = nullptr;
90     uint32_t len = 0;
91     if (!CheckAndGetJsProperty(ctx, valObject, &pTab, &len)) {
92         return;
93     }
94     pointInfo.SetDisplay(true);
95     for (uint32_t i = 0; i < len; i++) {
96         const char* key = JS_AtomToCString(ctx, pTab[i].atom);
97         if (key == nullptr) {
98             JS_FreeAtom(ctx, pTab[i].atom);
99             LOGW("key is null. Ignoring!");
100             continue;
101         }
102         JSValue val = JS_GetProperty(ctx, valObject, pTab[i].atom);
103         if (JS_IsString(val) || JS_IsNumber(val) || JS_IsBool(val)) {
104             static const LinearMapNode<void (*)(const char*, PointInfo&)> chartOptionsPointMap[] = {
105                 { "display",
106                     [](const char* valStr, PointInfo& pointInfo) {
107                         pointInfo.SetDisplay(StringToBool(valStr));
108                     } },
109                 { "fillColor",
110                     [](const char* valStr, PointInfo& pointInfo) {
111                         pointInfo.SetFillColor(Color::FromString(valStr));
112                     } },
113                 { "shape",
114                     [](const char* valStr, PointInfo& pointInfo) {
115                         PointShape shape =
116                             (strcmp(valStr, "circle") == 0)
117                                 ? PointShape::CIRCLE
118                                 : (strcmp(valStr, "square") == 0) ? PointShape::SQUARE : PointShape::TRIANGLE;
119                         pointInfo.SetPointShape(shape);
120                     } },
121                 { "size",
122                     [](const char* valStr, PointInfo& pointInfo) {
123                         pointInfo.SetPointSize(StringToDimension(valStr));
124                     } },
125                 { "strokeColor",
126                     [](const char* valStr, PointInfo& pointInfo) {
127                         pointInfo.SetStrokeColor(Color::FromString(valStr));
128                     } },
129                 { "strokeWidth",
130                     [](const char* valStr, PointInfo& pointInfo) {
131                         pointInfo.SetPointStrokeWidth(StringToDimension(valStr));
132                     } },
133             };
134             auto iter = BinarySearchFindIndex(chartOptionsPointMap, ArraySize(chartOptionsPointMap), key);
135             if (iter != -1) {
136                 ScopedString styleVal(ctx, val);
137                 chartOptionsPointMap[iter].value(styleVal.get(), pointInfo);
138             } else {
139                 LOGD("key : %{public}s unsupported. Ignoring!", key);
140             }
141         } else {
142             LOGD("key : %{public}s, value of unsupported type. Ignoring!", key);
143         }
144         JS_FreeAtom(ctx, pTab[i].atom);
145         JS_FreeCString(ctx, key);
146         JS_FreeValue(ctx, val);
147     }
148     js_free(ctx, pTab);
149 }
150 
GetChartAttrOptionsSeriesLineStyle(JSContext * ctx,JSValueConst valObject,ChartOptions & chartOptions)151 void GetChartAttrOptionsSeriesLineStyle(JSContext* ctx, JSValueConst valObject, ChartOptions& chartOptions)
152 {
153     JSPropertyEnum* pTab = nullptr;
154     uint32_t len = 0;
155     if (!CheckAndGetJsProperty(ctx, valObject, &pTab, &len)) {
156         return;
157     }
158     for (uint32_t i = 0; i < len; i++) {
159         const char* key = JS_AtomToCString(ctx, pTab[i].atom);
160         if (key == nullptr) {
161             JS_FreeAtom(ctx, pTab[i].atom);
162             LOGW("key is null. Ignoring!");
163             continue;
164         }
165         JSValue val = JS_GetProperty(ctx, valObject, pTab[i].atom);
166         if (JS_IsString(val) || JS_IsBool(val) || JS_IsNumber(val)) {
167             static const LinearMapNode<void (*)(const char*, ChartOptions&)>
168                 chartOptionsSeriesLinestyleMap[] = {
169                     { "lineGradient",
170                         [](const char* valStr, ChartOptions& chartOptions) {
171                             chartOptions.SetWholeLineGradient(StringToBool(valStr));
172                         } },
173                     { "smooth",
174                         [](const char* valStr, ChartOptions& chartOptions) {
175                             chartOptions.SetSmoothFlag(StringToBool(valStr));
176                         } },
177                     { "targetColor",
178                         [](const char* valStr, ChartOptions& chartOptions) {
179                             chartOptions.SetTargetColor(Color::FromString(valStr));
180                         } },
181                     { "width",
182                         [](const char* valStr, ChartOptions& chartOptions) {
183                             chartOptions.SetLineWidth(StringToDouble(valStr));
184                         } },
185                 };
186             auto iter =
187                 BinarySearchFindIndex(chartOptionsSeriesLinestyleMap, ArraySize(chartOptionsSeriesLinestyleMap), key);
188             if (iter != -1) {
189                 ScopedString styleVal(ctx, val);
190                 chartOptionsSeriesLinestyleMap[iter].value(styleVal.get(), chartOptions);
191             } else {
192                 LOGD("key : %{public}s unsupported. Ignoring!", key);
193             }
194         } else {
195             LOGD("value of unsupported type. Ignoring!");
196         }
197         JS_FreeAtom(ctx, pTab[i].atom);
198         JS_FreeCString(ctx, key);
199         JS_FreeValue(ctx, val);
200     }
201     js_free(ctx, pTab);
202 }
203 
GetChartAttrOptionsSeriesLoop(JSContext * ctx,JSValueConst valObject,ChartOptions & chartOptions)204 void GetChartAttrOptionsSeriesLoop(JSContext* ctx, JSValueConst valObject, ChartOptions& chartOptions)
205 {
206     JSPropertyEnum* pTab = nullptr;
207     uint32_t len = 0;
208     if (!CheckAndGetJsProperty(ctx, valObject, &pTab, &len)) {
209         return;
210     }
211     chartOptions.SetLoop(true);
212     for (uint32_t i = 0; i < len; i++) {
213         const char* key = JS_AtomToCString(ctx, pTab[i].atom);
214         if (key == nullptr) {
215             JS_FreeAtom(ctx, pTab[i].atom);
216             LOGW("key is null. Ignoring!");
217             continue;
218         }
219         JSValue val = JS_GetProperty(ctx, valObject, pTab[i].atom);
220         if (JS_IsString(val) || JS_IsBool(val) || JS_IsNumber(val)) {
221             static const LinearMapNode<void (*)(const char*, ChartOptions&)>
222                 chartOptionsSeriesLoopMap[] = {
223                     { "gradient",
224                         [](const char* valStr, ChartOptions& chartOptions) {
225                             chartOptions.SetLineGradient(StringToBool(valStr));
226                         } },
227                     { "margin",
228                         [](const char* valStr, ChartOptions& chartOptions) {
229                             chartOptions.SetErasePointNumber(StringUtils::StringToInt(valStr));
230                         } },
231                 };
232             auto iter = BinarySearchFindIndex(chartOptionsSeriesLoopMap, ArraySize(chartOptionsSeriesLoopMap), key);
233             if (iter != -1) {
234                 ScopedString styleVal(ctx, val);
235                 chartOptionsSeriesLoopMap[iter].value(styleVal.get(), chartOptions);
236             } else {
237                 LOGD("key : %{public}s unsupported. Ignoring!", key);
238             }
239         } else {
240             LOGD("value of unsupported type. Ignoring!");
241         }
242         JS_FreeAtom(ctx, pTab[i].atom);
243         JS_FreeCString(ctx, key);
244         JS_FreeValue(ctx, val);
245     }
246     js_free(ctx, pTab);
247 }
248 
GetChartAttrOptionsSeries(JSContext * ctx,JSValueConst valObject,ChartOptions & chartOptions)249 void GetChartAttrOptionsSeries(JSContext* ctx, JSValueConst valObject, ChartOptions& chartOptions)
250 {
251     JSPropertyEnum* pTab = nullptr;
252     uint32_t len = 0;
253     if (!CheckAndGetJsProperty(ctx, valObject, &pTab, &len)) {
254         return;
255     }
256     for (uint32_t i = 0; i < len; i++) {
257         const char* key = JS_AtomToCString(ctx, pTab[i].atom);
258         if (key == nullptr) {
259             JS_FreeAtom(ctx, pTab[i].atom);
260             LOGW("key is null. Ignoring!");
261             continue;
262         }
263         JSValue val = JS_GetProperty(ctx, valObject, pTab[i].atom);
264         if (JS_IsObject(val)) {
265             static const LinearMapNode<void (*)(JSContext*, JSValueConst, ChartOptions&)> chartOptionsSeriesMap[] = {
266                 { "bottomPoint",
267                     [](JSContext* ctx, JSValueConst valObject, ChartOptions& chartOptions) {
268                         PointInfo pointInfo;
269                         GetAttrOptionsSeriesPoint(ctx, valObject, pointInfo);
270                         chartOptions.SetBottomPoint(pointInfo);
271                     } },
272                 { "headPoint",
273                     [](JSContext* ctx, JSValueConst valObject, ChartOptions& chartOptions) {
274                         PointInfo pointInfo;
275                         GetAttrOptionsSeriesPoint(ctx, valObject, pointInfo);
276                         chartOptions.SetHeadPoint(pointInfo);
277                     } },
278                 { "lineStyle",
279                     [](JSContext* ctx, JSValueConst valObject, ChartOptions& chartOptions) {
280                         GetChartAttrOptionsSeriesLineStyle(ctx, valObject, chartOptions);
281                     } },
282                 { "loop",
283                     [](JSContext* ctx, JSValueConst valObject, ChartOptions& chartOptions) {
284                         GetChartAttrOptionsSeriesLoop(ctx, valObject, chartOptions);
285                     } },
286 
287                 { "topPoint",
288                     [](JSContext* ctx, JSValueConst valObject, ChartOptions& chartOptions) {
289                         PointInfo pointInfo;
290                         GetAttrOptionsSeriesPoint(ctx, valObject, pointInfo);
291                         chartOptions.SetTopPoint(pointInfo);
292                     } },
293             };
294             auto iter = BinarySearchFindIndex(chartOptionsSeriesMap, ArraySize(chartOptionsSeriesMap), key);
295             if (iter != -1) {
296                 chartOptionsSeriesMap[iter].value(ctx, val, chartOptions);
297             } else {
298                 LOGD("key : %{public}s unsupported. Ignoring!", key);
299             }
300         } else {
301             LOGD("value of unsupported type. Ignoring!");
302         }
303         JS_FreeAtom(ctx, pTab[i].atom);
304         JS_FreeCString(ctx, key);
305         JS_FreeValue(ctx, val);
306     }
307     js_free(ctx, pTab);
308 }
309 
ParseTextInfoAndSegmentInfo(JSContext * ctx,JSValue val,const char * key,TextInfo & textInfo,SegmentInfo & segmentInfo)310 void ParseTextInfoAndSegmentInfo(
311     JSContext* ctx, JSValue val, const char* key, TextInfo& textInfo, SegmentInfo& segmentInfo)
312 {
313     ScopedString stringVal(ctx, val);
314     const char* convertedVal = stringVal.get();
315     if (strcmp(key, "description") == 0) {
316         textInfo.SetTextValue(convertedVal);
317     } else if (strcmp(key, "textLocation") == 0) {
318         if (strcmp(convertedVal, "top") == 0) {
319             textInfo.SetPlacement(Placement::TOP);
320         } else if (strcmp(convertedVal, "bottom") == 0) {
321             textInfo.SetPlacement(Placement::BOTTOM);
322         } else if (strcmp(convertedVal, "none") == 0) {
323             textInfo.SetPlacement(Placement::NONE);
324         }
325     } else if (strcmp(key, "lineDash") == 0) {
326         std::vector<std::string> dash;
327         StringUtils::StringSplitter(convertedVal, ',', dash);
328         if (dash.size() > 0) {
329             segmentInfo.SetLineType(dash[0] == "dashed" ? LineType::DASHED : LineType::SOLID);
330         }
331         if (dash.size() > 1) {
332             segmentInfo.SetSolidWidth(StringToDouble(dash[1]));
333         }
334         if (dash.size() > 2) {
335             segmentInfo.SetSpaceWidth(StringToDouble(dash[2]));
336         }
337     } else if (strcmp(key, "lineColor") == 0) {
338         segmentInfo.SetSegmentColor(Color::FromString(convertedVal));
339     } else if (strcmp(key, "textColor") == 0) {
340         textInfo.SetColor(Color::FromString(convertedVal));
341     } else {
342         LOGW("key is %{public}s. Ignoring!", key);
343     }
344 }
345 
ParseAttrDataStyle(JSContext * ctx,JSValueConst valObject,LineInfo & line,double index)346 void ParseAttrDataStyle(JSContext* ctx, JSValueConst valObject, LineInfo& line, double index)
347 {
348     JSPropertyEnum* pTab = nullptr;
349     uint32_t len = 0;
350     PointInfo pointInfo;
351     TextInfo textInfo;
352     SegmentInfo segmentInfo;
353     if (!CheckAndGetJsProperty(ctx, valObject, &pTab, &len)) {
354         return;
355     }
356     for (uint32_t i = 0; i < len; i++) {
357         const char* key = JS_AtomToCString(ctx, pTab[i].atom);
358         if (key == nullptr) {
359             JS_FreeAtom(ctx, pTab[i].atom);
360             LOGW("key is null. Ignoring!");
361             continue;
362         }
363         JSValue val = JS_GetProperty(ctx, valObject, pTab[i].atom);
364         if (JS_IsString(val)) {
365             ParseTextInfoAndSegmentInfo(ctx, val, key, textInfo, segmentInfo);
366         } else if (JS_IsObject(val)) {
367             if (strcmp(key, "pointStyle") == 0) {
368                 GetAttrOptionsSeriesPoint(ctx, val, pointInfo);
369             }
370         } else if (JS_IsNumber(val)) {
371             if (strcmp(key, "value") == 0) {
372                 ScopedString onlyYStringVal(ctx, val);
373                 const char* onlyY = onlyYStringVal.get();
374                 pointInfo.SetX(static_cast<double>(index));
375                 pointInfo.SetY(StringToDouble(onlyY));
376             }
377         } else {
378             LOGW("key is %{public}s. Ignoring!", key);
379         }
380         line.SetPointInfo(pointInfo);
381         line.SetTextInfo(textInfo);
382         line.SetSegmentInfo(segmentInfo);
383         JS_FreeAtom(ctx, pTab[i].atom);
384         JS_FreeCString(ctx, key);
385         JS_FreeValue(ctx, val);
386     }
387     js_free(ctx, pTab);
388 }
389 
GetAttrDataSetData(JSContext * ctx,JSValueConst dataArrayVal,MainChart & dataSet)390 void GetAttrDataSetData(JSContext* ctx, JSValueConst dataArrayVal, MainChart& dataSet)
391 {
392     int32_t length = QJSUtils::JsGetArrayLength(ctx, dataArrayVal);
393     std::vector<LineInfo> line;
394     for (int32_t j = 0; j < length; ++j) {
395         JSValue dataArrayItemVal = JS_GetPropertyUint32(ctx, dataArrayVal, j);
396         LineInfo lineInfo;
397         PointInfo pointInfo;
398         if (JS_IsArray(ctx, dataArrayItemVal)) { // Coordinates are two-dimensional arrays
399             int32_t dataArrayIterLen = QJSUtils::JsGetArrayLength(ctx, dataArrayItemVal);
400             if (dataArrayIterLen != VALID_ARRAY_LENGTH) { // Check coordinates are not two-dimensional arrays
401                 LOGW("Attr Datasets data type unsupported!");
402                 JS_FreeValue(ctx, dataArrayItemVal);
403                 continue;
404             }
405             JSValue xVal = JS_GetPropertyUint32(ctx, dataArrayItemVal, ARRAY_X_VALUE);
406             ScopedString xStringVal(ctx, xVal);
407             const char* x = xStringVal.get();
408             pointInfo.SetX(StringToDouble(x));
409 
410             JSValue yVal = JS_GetPropertyUint32(ctx, dataArrayItemVal, ARRAY_Y_VALUE);
411             ScopedString yStringVal(ctx, yVal);
412             const char* y = yStringVal.get();
413             pointInfo.SetY(StringToDouble(y));
414             lineInfo.SetPointInfo(pointInfo);
415             JS_FreeValue(ctx, xVal);
416             JS_FreeValue(ctx, yVal);
417         } else if (JS_IsNumber(dataArrayItemVal)) { // Coordinates as a one-dimensional array
418             ScopedString onlyYStringVal(ctx, dataArrayItemVal);
419             const char* onlyY = onlyYStringVal.get();
420             // When only the Y value is passed in, the X value is sequentially +1
421             pointInfo.SetX(static_cast<double>(j));
422             pointInfo.SetY(StringToDouble(onlyY));
423             lineInfo.SetPointInfo(pointInfo);
424         } else if (JS_IsObject(dataArrayItemVal)) {
425             ParseAttrDataStyle(ctx, dataArrayItemVal, lineInfo, j);
426         } else {
427             LOGW("value of unsupported type. Ignoring!");
428             JS_FreeValue(ctx, dataArrayItemVal);
429             continue;
430         }
431         line.push_back(lineInfo);
432         JS_FreeValue(ctx, dataArrayItemVal);
433     }
434     dataSet.SetData(line);
435 }
436 
GetAttrDataset(JSContext * ctx,JSValueConst valObject,MainChart & dataSet)437 void GetAttrDataset(JSContext* ctx, JSValueConst valObject, MainChart& dataSet)
438 {
439     JSPropertyEnum* pTab = nullptr;
440     uint32_t len = 0;
441     if (!CheckAndGetJsProperty(ctx, valObject, &pTab, &len)) {
442         return;
443     }
444     for (uint32_t i = 0; i < len; i++) {
445         const char* key = JS_AtomToCString(ctx, pTab[i].atom);
446         if (key == nullptr) {
447             JS_FreeAtom(ctx, pTab[i].atom);
448             LOGW("key is null. Ignoring!");
449             continue;
450         }
451         JSValue val = JS_GetProperty(ctx, valObject, pTab[i].atom);
452         if (JS_IsNumber(val) || JS_IsBool(val) || JS_IsString(val)) {
453             ScopedString styleVal(ctx, val);
454             const char* valStr = styleVal.get();
455             if (strcmp(key, "gradient") == 0) {
456                 dataSet.SetGradient(StringToBool(valStr));
457             } else if (strcmp(key, "strokeColor") == 0) {
458                 dataSet.SetStrokeColor(Color::FromString(valStr));
459             } else if (strcmp(key, "fillColor") == 0) {
460                 dataSet.SetFillColor(Color::FromString(valStr));
461             } else {
462                 LOGD("key : %{public}s unsupported. Ignoring!", key);
463             }
464         } else if (JS_IsArray(ctx, val) && strcmp(key, "data") == 0) {
465             GetAttrDataSetData(ctx, val, dataSet);
466         } else {
467             LOGD("value of unsupported type. Ignoring!");
468         }
469         JS_FreeAtom(ctx, pTab[i].atom);
470         JS_FreeCString(ctx, key);
471         JS_FreeValue(ctx, val);
472     }
473     js_free(ctx, pTab);
474 }
475 
ParseAttrSegment(JSContext * ctx,JSValue valObject,Segment & segment)476 void ParseAttrSegment(JSContext* ctx, JSValue valObject, Segment& segment)
477 {
478     JSPropertyEnum* pTab = nullptr;
479     uint32_t len = 0;
480     if (!CheckAndGetJsProperty(ctx, valObject, &pTab, &len)) {
481         return;
482     }
483     for (uint32_t i = 0; i < len; i++) {
484         const char* key = JS_AtomToCString(ctx, pTab[i].atom);
485         if (key == nullptr) {
486             JS_FreeAtom(ctx, pTab[i].atom);
487             LOGW("key is null. Ignoring!");
488             continue;
489         }
490         JSValue val = JS_GetProperty(ctx, valObject, pTab[i].atom);
491         if (JS_IsNumber(val) || JS_IsString(val)) {
492             ScopedString styleVal(ctx, val);
493             const char* valStr = styleVal.get();
494             if (strcmp(key, "value") == 0) {
495                 segment.SetValue(StringToDouble(valStr));
496             } else if (strcmp(key, "startColor") == 0) {
497                 segment.SetStartColor(Color::FromString(valStr));
498                 segment.SetColorType(SegmentStyleType::USE_COLOR);
499             } else if (strcmp(key, "endColor") == 0) {
500                 segment.SetEndColor(Color::FromString(valStr));
501                 segment.SetColorType(SegmentStyleType::USE_COLOR);
502             } else if (strcmp(key, "name") == 0) {
503                 segment.SetSegmentName(valStr);
504             } else {
505                 LOGD("key : %{public}s unsupported. Ignoring!", key);
506             }
507         } else {
508             LOGD("value of unsupported type. Ignoring!");
509         }
510         JS_FreeAtom(ctx, pTab[i].atom);
511         JS_FreeCString(ctx, key);
512         JS_FreeValue(ctx, val);
513     }
514     js_free(ctx, pTab);
515 }
516 
517 } // namespace
518 
GetAttrOptionsObject(JSContext * ctx,JSValueConst valObject)519 void ChartBridge::GetAttrOptionsObject(JSContext* ctx, JSValueConst valObject)
520 {
521     JSPropertyEnum* pTab = nullptr;
522     uint32_t len = 0;
523     if (!CheckAndGetJsProperty(ctx, valObject, &pTab, &len)) {
524         return;
525     }
526     for (uint32_t i = 0; i < len; i++) {
527         const char* key = JS_AtomToCString(ctx, pTab[i].atom);
528         if (key == nullptr) {
529             JS_FreeAtom(ctx, pTab[i].atom);
530             LOGW("key is null. Ignoring!");
531             continue;
532         }
533         JSValue val = JS_GetProperty(ctx, valObject, pTab[i].atom);
534         if (JS_IsObject(val) || JS_IsString(val) || JS_IsBool(val) || JS_IsNumber(val)) {
535             static const LinearMapNode<void (*)(JSContext*, JSValueConst, ChartOptions&)> chartOptionsMap[] = {
536                 { "series",
537                     [](JSContext* ctx, JSValueConst valObject, ChartOptions& chartOptions) {
538                         GetChartAttrOptionsSeries(ctx, valObject, chartOptions);
539                     } },
540                 { "xAxis",
541                     [](JSContext* ctx, JSValueConst valObject, ChartOptions& chartOptions) {
542                         AxisOption xAxis;
543                         GetAttrOptionsAxis(ctx, valObject, xAxis);
544                         chartOptions.SetXAxis(xAxis);
545                     } },
546                 { "yAxis",
547                     [](JSContext* ctx, JSValueConst valObject, ChartOptions& chartOptions) {
548                         AxisOption yAxis;
549                         GetAttrOptionsAxis(ctx, valObject, yAxis);
550                         chartOptions.SetYAxis(yAxis);
551                     } },
552             };
553             auto iter = BinarySearchFindIndex(chartOptionsMap, ArraySize(chartOptionsMap), key);
554             if (iter != -1) {
555                 chartOptionsMap[iter].value(ctx, val, chartOptions_);
556             } else {
557                 LOGD("key : %{public}s unsupported. Ignoring!", key);
558             }
559         } else {
560             LOGD("value of unsupported type. Ignoring!");
561         }
562         JS_FreeAtom(ctx, pTab[i].atom);
563         JS_FreeCString(ctx, key);
564         JS_FreeValue(ctx, val);
565     }
566     js_free(ctx, pTab);
567 }
568 
GetAttrDatasets(JSContext * ctx,JSValueConst valArray)569 void ChartBridge::GetAttrDatasets(JSContext* ctx, JSValueConst valArray)
570 {
571     int32_t len = QJSUtils::JsGetArrayLength(ctx, valArray);
572     for (int32_t i = 0; i < len; ++i) {
573         JSValue itemVal = JS_GetPropertyUint32(ctx, valArray, i);
574         MainChart chart;
575         if (JS_IsObject(itemVal)) {
576             GetAttrDataset(ctx, itemVal, chart);
577             datasets_.push_back(chart);
578         }
579         JS_FreeValue(ctx, itemVal);
580     }
581 }
582 
ParseAttrSegmentArray(JSContext * ctx,JSValueConst valArray)583 void ChartBridge::ParseAttrSegmentArray(JSContext* ctx, JSValueConst valArray)
584 {
585     int32_t len = QJSUtils::JsGetArrayLength(ctx, valArray);
586     for (int32_t i = 0; i < len; ++i) {
587         JSValue itemVal = JS_GetPropertyUint32(ctx, valArray, i);
588         if (JS_IsObject(itemVal)) {
589             Segment segment;
590             ParseAttrSegment(ctx, itemVal, segment);
591             segments_.emplace_back(std::move(segment));
592         }
593         JS_FreeValue(ctx, itemVal);
594     }
595 }
596 
ParseAttrSingleSegment(JSContext * ctx,JSValueConst valObject)597 void ChartBridge::ParseAttrSingleSegment(JSContext* ctx, JSValueConst valObject)
598 {
599     if (!JS_IsObject(valObject)) {
600         LOGW("fail to parse segment, because it is not an object");
601         return;
602     }
603     segments_.clear();
604     Segment segment;
605     ParseAttrSegment(ctx, valObject, segment);
606     segments_.emplace_back(std::move(segment));
607 }
608 
609 } // namespace OHOS::Ace::Framework