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