1 /*
2 * Copyright (c) 2023 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 "HmSymbolConfig_ohos.h"
17
18 #include <functional>
19 #include <fstream>
20
21 #include "securec.h"
22
23 #include "include/private/SkOnce.h"
24
25 #ifdef SK_BUILD_FONT_MGR_FOR_OHOS
26 #include <parameters.h>
27 #endif
28
29 #ifdef ENABLE_DEBUG
30
31 #define LOGE(fmt, args...) \
32 printf("E %s:%d %s - " fmt, basename(__FILE__), __LINE__, __FUNCTION__, ##args)
33 #define LOGI(fmt, args...) \
34 printf("I %s:%d - " fmt, __FUNCTION__, __LINE__, ##args)
35 #define LOGW(fmt, args...) \
36 printf("W %s:%d %s - " fmt, basename(__FILE__), __LINE__, __FUNCTION__, ##args)
37
38 #else
39
40 #define LOGE SkDEBUGF
41 #define LOGI SkDEBUGF
42 #define LOGW SkDEBUGF
43
44 #endif
45
46 using PiecewiseParaKeyFunc = std::function<void(const char*, const Json::Value&, PiecewiseParameter&)>;
47 using SymbolKeyFunc = std::function<void(const char*, const Json::Value&, SymbolLayersGroups&)>;
48 using SymnolAniFunc = std::function<void(const char*, const Json::Value&, AnimationPara&)>;
49
50 using SymbolKeyFuncMap = std::unordered_map<std::string, SymbolKeyFunc>;
51 const char SPECIAL_ANIMATIONS[] = "special_animations";
52 const char COMMON_ANIMATIONS[] = "common_animations";
53 const char SYMBOL_LAYERS_GROUPING[] = "symbol_layers_grouping";
54 const char ANIMATION_TYPE[] = "animation_type";
55 const char ANIMATION_TYPES[] = "animation_types";
56 const char ANIMATION_PARAMETERS[] = "animation_parameters";
57 const char ANIMATION_MODE[] = "animation_mode";
58 const char GROUP_PARAMETERS[] = "group_parameters";
59 const char CURVE[] = "curve";
60 const char CURVE_ARGS[] = "curve_args";
61 const char DURATION[] = "duration";
62 const char DELAY[] = "delay";
63 const char NATIVE_GLYPH_ID[] = "native_glyph_id";
64 const char SYMBOL_GLYPH_ID[] = "symbol_glyph_id";
65 const char LAYERS[] = "layers";
66 const char RENDER_MODES[] = "render_modes";
67 const char MODE[] = "mode";
68 const char RENDER_GROUPS[] = "render_groups";
69 const char GROUP_INDEXES[] = "group_indexes";
70 const char DEFAULT_COLOR[] = "default_color";
71 const char FIX_ALPHA[] = "fix_alpha";
72 const char LAYER_INDEXES[] = "layer_indexes";
73 const char MASK_INDEXES[] = "mask_indexes";
74 const char GROUP_SETTINGS[] = "group_settings";
75 const char ANIMATION_INDEX[] = "animation_index";
76 const char COMMON_SUB_TYPE[] = "common_sub_type";
77
78 const int NO_ERROR = 0; // no error
79 const int ERROR_CONFIG_NOT_FOUND = 1; // the configuration document is not found
80 const int ERROR_CONFIG_FORMAT_NOT_SUPPORTED = 2; // the formation of configuration is not supported
81 const int ERROR_CONFIG_INVALID_VALUE_TYPE = 4; // invalid value type in the configuration
82 const int ERROR_TYPE_COUNT = 11;
83
84 static const std::map<std::string, AnimationType> ANIMATIONS_TYPES = {
85 {"scale", AnimationType::SCALE_TYPE},
86 {"appear", AnimationType::APPEAR_TYPE},
87 {"disappear", AnimationType::DISAPPEAR_TYPE},
88 {"bounce", AnimationType::BOUNCE_TYPE},
89 {"variable_color", AnimationType::VARIABLE_COLOR_TYPE},
90 {"pulse", AnimationType::PULSE_TYPE},
91 {"replace_appear", AnimationType::REPLACE_APPEAR_TYPE},
92 {"replace_disappear", AnimationType::REPLACE_DISAPPEAR_TYPE}};
93
94 static const std::map<std::string, CurveType> CURVE_TYPES = {
95 {"spring", CurveType::SPRING},
96 {"linear", CurveType::LINEAR},
97 {"friction", CurveType::FRICTION},
98 {"sharp", CurveType::SHARP}};
99
100 /* To get the display text of an error
101 * \param err the id of an error
102 * \return The text to explain the error
103 */
ErrInfoToString(int err)104 const char* ErrInfoToString(int err)
105 {
106 const static std::array<const char*, ERROR_TYPE_COUNT> errInfoToString{
107 "successful", // NO_ERROR = 0
108 "config file is not found", // ERROR_CONFIG_NOT_FOUND
109 "the format of config file is not supported", // ERROR_CONFIG_FORMAT_NOT_SUPPORTED
110 "missing tag", // ERROR_CONFIG_MISSING_TAG
111 "invalid value type", // ERROR_CONFIG_INVALID_VALUE_TYPE
112 "font file is not exist", // ERROR_FONT_NOT_EXIST
113 "invalid font stream", // ERROR_FONT_INVALID_STREAM
114 "no font stream", // ERROR_FONT_NO_STREAM
115 "family is not found", // ERROR_FAMILY_NOT_FOUND
116 "no available family in the system", //ERROR_NO_AVAILABLE_FAMILY
117 "no such directory" // ERROR_DIR_NOT_FOUND
118 };
119 if (err >= 0 && err < ERROR_TYPE_COUNT) {
120 return errInfoToString[err];
121 }
122 return "unknown error";
123 }
124
125 /* To log the error information
126 * \param err the id of an error
127 * \param key the key which indicates the the part with the error
128 * \param expected the expected type of json node.
129 * \n It's used only for err 'ERROR_CONFIG_INVALID_VALUE_TYPE'
130 * \param actual the actual type of json node.
131 * \n It's used only for err 'ERROR_CONFIG_INVALID_VALUE_TYPE'
132 * \return err
133 */
LogErrInfo(int err,const char * key,Json::ValueType expected=Json::nullValue,Json::ValueType actual=Json::nullValue)134 int LogErrInfo(int err, const char* key, Json::ValueType expected = Json::nullValue,
135 Json::ValueType actual = Json::nullValue)
136 {
137 if (err != ERROR_CONFIG_INVALID_VALUE_TYPE) {
138 LOGE("%s : %s\n", ErrInfoToString(err), key);
139 } else {
140 const char* types[] = {
141 "null",
142 "int",
143 "unit",
144 "real",
145 "string",
146 "boolean",
147 "array",
148 "object",
149 };
150 int size = sizeof(types) / sizeof(char*);
151 if ((expected >= 0 && expected < size) &&
152 (actual >= 0 && actual < size)) {
153 LOGE("%s : '%s' should be '%s', but here it's '%s'\n",
154 ErrInfoToString(err), key, types[expected], types[actual]);
155 } else {
156 LOGE("%s : %s\n", ErrInfoToString(err), key);
157 }
158 }
159 return err;
160 }
161
162 /* To get the data of font configuration file
163 * \param fname the full name of the font configuration file
164 * \param[out] size the size of data returned to the caller
165 * \return The pointer of content of the file
166 * \note The returned pointer should be freed by the caller
167 */
GetDataFromFile(const char * fname,int & size)168 std::unique_ptr<char[]> GetDataFromFile(const char* fname, int& size)
169 {
170 auto file = std::make_unique<std::ifstream>(fname);
171 if (file == nullptr || !file->is_open()) {
172 size = 0;
173 return nullptr;
174 }
175
176 file->seekg(0, std::ios::end);
177 size = static_cast<int>(file->tellg()); // get the length of file
178 if (size <= 0) {
179 size = 0;
180 return nullptr;
181 }
182 auto data = std::make_unique<char[]>(size);
183 if (data == nullptr) {
184 size = 0;
185 return nullptr;
186 }
187 file->seekg(0, std::ios::beg);
188 file->read(data.get(), size); // read data a block
189 return data;
190 }
191
GetHmSymbolEnable()192 bool HmSymbolConfig_OHOS::GetHmSymbolEnable()
193 {
194 #ifdef SK_BUILD_FONT_MGR_FOR_OHOS
195 static bool isHMSymbolEnable =
196 (std::atoi(OHOS::system::GetParameter("persist.sys.graphic.hmsymbolcfg.enable", "1").c_str()) != 0);
197 return isHMSymbolEnable;
198 #else
199 return true;
200 #endif
201 }
202
GetInstance()203 HmSymbolConfig_OHOS* HmSymbolConfig_OHOS::GetInstance()
204 {
205 static HmSymbolConfig_OHOS singleton;
206 return &singleton;
207 }
208
GetSymbolLayersGroups(uint16_t glyphId)209 SymbolLayersGroups HmSymbolConfig_OHOS::GetSymbolLayersGroups(uint16_t glyphId)
210 {
211 SymbolLayersGroups symbolLayersGroups;
212 if (hmSymbolConfig_.size() == 0) {
213 return symbolLayersGroups;
214 }
215 auto iter = hmSymbolConfig_.find(glyphId);
216 if (iter != hmSymbolConfig_.end()) {
217 symbolLayersGroups = iter->second;
218 }
219 return symbolLayersGroups;
220 }
221
GetGroupParameters(AnimationType type,uint16_t groupSum,uint16_t animationMode,CommonSubType commonSubType)222 std::vector<std::vector<PiecewiseParameter>> HmSymbolConfig_OHOS::GetGroupParameters(AnimationType type,
223 uint16_t groupSum, uint16_t animationMode, CommonSubType commonSubType)
224 {
225 std::vector<std::vector<PiecewiseParameter>> groupParametersOut;
226 if (animationInfos_.empty()) {
227 return groupParametersOut;
228 }
229 std::unordered_map<AnimationType, AnimationInfo>::iterator iter = animationInfos_.find(type);
230 if (iter == animationInfos_.end()) {
231 return groupParametersOut;
232 }
233 auto key = EncodeAnimationAttribute(groupSum, animationMode, commonSubType);
234 auto para = iter->second.animationParas.find(key);
235 if (para != iter->second.animationParas.end()) {
236 groupParametersOut = para->second.groupParameters;
237 }
238 return groupParametersOut;
239 }
240
241 /* check the system font configuration document
242 * \param fname the full name of the font configuration document
243 * \return NO_ERROR successful
244 * \return ERROR_CONFIG_NOT_FOUND config document is not found
245 * \return ERROR_CONFIG_FORMAT_NOT_SUPPORTED config document format is not supported
246 */
CheckConfigFile(const char * fname,Json::Value & root)247 int HmSymbolConfig_OHOS::CheckConfigFile(const char* fname, Json::Value& root)
248 {
249 int size = 0;
250 auto data = GetDataFromFile(fname, size);
251 if (data == nullptr) {
252 return LogErrInfo(ERROR_CONFIG_NOT_FOUND, fname);
253 }
254 JSONCPP_STRING errs;
255 Json::CharReaderBuilder charReaderBuilder;
256 std::unique_ptr<Json::CharReader> jsonReader(charReaderBuilder.newCharReader());
257 bool isJson = jsonReader->parse(data.get(), data.get() + size, &root, &errs);
258 if (!isJson || !errs.empty()) {
259 return LogErrInfo(ERROR_CONFIG_FORMAT_NOT_SUPPORTED, fname);
260 }
261 return NO_ERROR;
262 }
263
ParseConfigOfHmSymbol(const char * fname,SkString fontDir)264 int HmSymbolConfig_OHOS::ParseConfigOfHmSymbol(const char* fname, SkString fontDir)
265 {
266 std::lock_guard<std::mutex> lock(hmSymbolMut_);
267 if (GetInit()) {
268 return NO_ERROR;
269 }
270 Clear();
271 const int fontEndSize = 2;
272 int len = strlen(fname) + (fontDir.size() + fontEndSize);
273 char fullname[len];
274 if (memset_s(fullname, len, 0, len) != 0 ||
275 strcpy_s(fullname, len, fontDir.c_str()) != 0) {
276 return ERROR_CONFIG_NOT_FOUND;
277 }
278 #if defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_WIN)
279 if (fontDir[fontDir.size() - 1] != '\\') {
280 strcat_s(fullname, len, "\\");
281 }
282 #else
283 if (fontDir[fontDir.size() - 1] != '/') {
284 strcat_s(fullname, len, "/");
285 }
286 #endif
287 if (strcat_s(fullname, len, fname) != 0) {
288 return ERROR_CONFIG_NOT_FOUND;
289 }
290 Json::Value root;
291 int err = CheckConfigFile(fullname, root);
292 if (err != NO_ERROR) {
293 return err;
294 }
295
296 const char* key = nullptr;
297 std::string tags[] = {COMMON_ANIMATIONS, SPECIAL_ANIMATIONS, SYMBOL_LAYERS_GROUPING};
298 for (unsigned int i = 0; i < sizeof(tags) / sizeof(tags[0]); i++) {
299 key = tags[i].c_str();
300 if (!root.isMember(key) || !root[key].isArray()) {
301 continue;
302 }
303 if (!strcmp(key, COMMON_ANIMATIONS) || !strcmp(key, SPECIAL_ANIMATIONS)) {
304 ParseSymbolAnimations(root[key], &animationInfos_);
305 } else {
306 ParseSymbolLayersGrouping(root[key]);
307 }
308 }
309 root.clear();
310 SetInit(true);
311 return NO_ERROR;
312 }
313
ParseSymbolAnimations(const Json::Value & root,std::unordered_map<AnimationType,AnimationInfo> * animationInfos)314 void HmSymbolConfig_OHOS::ParseSymbolAnimations(const Json::Value& root,
315 std::unordered_map<AnimationType, AnimationInfo>* animationInfos)
316 {
317 for (unsigned int i = 0; i < root.size(); i++) {
318 if (!root[i].isObject()) {
319 SkDebugf("animation is not object!");
320 continue;
321 }
322
323 if (!root[i].isMember(ANIMATION_TYPE) || !root[i].isMember(ANIMATION_PARAMETERS)) {
324 continue;
325 }
326 AnimationInfo animationInfo;
327 if (!root[i][ANIMATION_TYPE].isString()) {
328 SkDebugf("animation_type is not string!");
329 continue;
330 }
331 const std::string animationType = root[i][ANIMATION_TYPE].asCString();
332 ParseAnimationType(animationType, animationInfo.animationType);
333
334 if (!root[i][ANIMATION_PARAMETERS].isArray()) {
335 SkDebugf("animation_parameters is not array!");
336 continue;
337 }
338 ParseSymbolAnimationParas(root[i][ANIMATION_PARAMETERS], animationInfo.animationParas);
339 animationInfos->insert({animationInfo.animationType, animationInfo});
340 }
341 }
342
EncodeAnimationAttribute(uint16_t groupSum,uint16_t animationMode,CommonSubType commonSubType)343 uint32_t HmSymbolConfig_OHOS::EncodeAnimationAttribute(uint16_t groupSum, uint16_t animationMode,
344 CommonSubType commonSubType)
345 {
346 uint32_t result = static_cast<uint32_t>(groupSum);
347 result = (result << oneByteBitsLen) + static_cast<uint32_t>(animationMode);
348 result = (result << oneByteBitsLen) + static_cast<uint32_t>(commonSubType);
349 return result;
350 }
351
ParseSymbolAnimationParas(const Json::Value & root,std::map<uint32_t,AnimationPara> & animationParas)352 void HmSymbolConfig_OHOS::ParseSymbolAnimationParas(const Json::Value& root,
353 std::map<uint32_t, AnimationPara>& animationParas)
354 {
355 for (unsigned int i = 0; i < root.size(); i++) {
356 if (!root[i].isObject()) {
357 SkDebugf("animation_parameter is not object!");
358 continue;
359 }
360 AnimationPara animationPara;
361 ParseSymbolAnimationPara(root[i], animationPara);
362 uint32_t attributeKey = EncodeAnimationAttribute(animationPara.groupParameters.size(),
363 animationPara.animationMode, animationPara.commonSubType);
364 animationParas.insert({attributeKey, animationPara});
365 }
366 }
367
ParseSymbolAnimationPara(const Json::Value & root,AnimationPara & animationPara)368 void HmSymbolConfig_OHOS::ParseSymbolAnimationPara(const Json::Value& root, AnimationPara& animationPara)
369 {
370 const char* key = nullptr;
371 std::string tags[] = {ANIMATION_MODE, COMMON_SUB_TYPE, GROUP_PARAMETERS};
372 using SymnolAniFuncMap = std::unordered_map<std::string, SymnolAniFunc>;
373 SymnolAniFuncMap funcMap = {
374 {ANIMATION_MODE, [](const char* key, const Json::Value& root, AnimationPara& animationPara)
375 {
376 if (!root[key].isInt()) {
377 SkDebugf("animation_mode is not int!");
378 return;
379 }
380 animationPara.animationMode = root[key].asInt();
381 }
382 },
383 {COMMON_SUB_TYPE, [this](const char* key, const Json::Value& root, AnimationPara& animationPara)
384 {
385 if (!root[key].isString()) {
386 SkDebugf("sub_type is not string!");
387 return;
388 }
389 const char* subTypeStr = root[key].asCString();
390 ParseSymbolCommonSubType(subTypeStr, animationPara.commonSubType);
391 }
392 },
393 {GROUP_PARAMETERS, [this](const char* key, const Json::Value& root, AnimationPara& animationPara)
394 {
395 if (!root[key].isArray()) {
396 SkDebugf("group_parameters is not array!");
397 return;
398 }
399 ParseSymbolGroupParas(root[key], animationPara.groupParameters);
400 }
401 }
402 };
403 for (unsigned int i = 0; i < sizeof(tags) / sizeof(tags[0]); i++) {
404 key = tags[i].c_str();
405 if (!root.isMember(key)) {
406 continue;
407 }
408 if (funcMap.count(key) > 0) {
409 funcMap[key](key, root, animationPara);
410 }
411 }
412 }
413
ParseSymbolCommonSubType(const char * subTypeStr,CommonSubType & commonSubType)414 void HmSymbolConfig_OHOS::ParseSymbolCommonSubType(const char* subTypeStr, CommonSubType& commonSubType)
415 {
416 using SymbolAniSubFuncMap = std::unordered_map<std::string, std::function<void(CommonSubType&)>>;
417 SymbolAniSubFuncMap funcMap = {
418 {
419 "up",
420 [](CommonSubType& commonSubType) {
421 commonSubType = CommonSubType::UP;
422 }
423 },
424 {
425 "down",
426 [](CommonSubType& commonSubType) {
427 commonSubType = CommonSubType::DOWN;
428 }
429 }
430 };
431 if (funcMap.count(subTypeStr) > 0) {
432 funcMap[subTypeStr](commonSubType);
433 return;
434 }
435 SkDebugf("%{public}s is invalid value!", subTypeStr);
436 }
437
ParseSymbolGroupParas(const Json::Value & root,std::vector<std::vector<PiecewiseParameter>> & groupParameters)438 void HmSymbolConfig_OHOS::ParseSymbolGroupParas(const Json::Value& root,
439 std::vector<std::vector<PiecewiseParameter>>& groupParameters)
440 {
441 for (unsigned int i = 0; i < root.size(); i++) {
442 if (!root[i].isArray()) {
443 SkDebugf("group_parameter is not array!");
444 continue;
445 }
446 std::vector<PiecewiseParameter> piecewiseParameters;
447 for (unsigned int j = 0; j < root[i].size(); j++) {
448 if (!root[i][j].isObject()) {
449 SkDebugf("piecewise_parameter is not object!");
450 continue;
451 }
452 PiecewiseParameter piecewiseParameter;
453 ParseSymbolPiecewisePara(root[i][j], piecewiseParameter);
454 piecewiseParameters.push_back(piecewiseParameter);
455 }
456
457 groupParameters.push_back(piecewiseParameters);
458 }
459 }
460
461
PiecewiseParaCurveCase(const char * key,const Json::Value & root,PiecewiseParameter & piecewiseParameter)462 static void PiecewiseParaCurveCase(const char* key, const Json::Value& root, PiecewiseParameter& piecewiseParameter)
463 {
464 if (!root[key].isString()) {
465 SkDebugf("curve is not string!");
466 return;
467 }
468 const std::string curveTypeStr = root[key].asCString();
469 auto iter = CURVE_TYPES.find(curveTypeStr);
470 if (iter != CURVE_TYPES.end()) {
471 piecewiseParameter.curveType = iter->second;
472 return;
473 }
474 SkDebugf("curve is invalid value!");
475 }
476
PiecewiseParaDurationCase(const char * key,const Json::Value & root,PiecewiseParameter & piecewiseParameter)477 static void PiecewiseParaDurationCase(const char* key, const Json::Value& root,
478 PiecewiseParameter& piecewiseParameter)
479 {
480 if (!root[key].isNumeric()) {
481 SkDebugf("duration is not numeric!");
482 return;
483 }
484 piecewiseParameter.duration = static_cast<uint32_t>(root[key].asDouble());
485 }
486
PiecewiseParaDelayCase(const char * key,const Json::Value & root,PiecewiseParameter & piecewiseParameter)487 static void PiecewiseParaDelayCase(const char* key, const Json::Value& root, PiecewiseParameter& piecewiseParameter)
488 {
489 if (!root[key].isNumeric()) {
490 SkDebugf("delay is not numeric!");
491 return;
492 }
493 piecewiseParameter.delay = static_cast<int>(root[key].asDouble());
494 }
495
ParseSymbolPiecewisePara(const Json::Value & root,PiecewiseParameter & piecewiseParameter)496 void HmSymbolConfig_OHOS::ParseSymbolPiecewisePara(const Json::Value& root, PiecewiseParameter& piecewiseParameter)
497 {
498 const char* key = nullptr;
499 std::string tags[] = {CURVE, CURVE_ARGS, DURATION, DELAY, "properties"};
500 using PiecewiseFuncMap = std::unordered_map<std::string, PiecewiseParaKeyFunc>;
501 PiecewiseFuncMap funcMap = {
502 {CURVE, PiecewiseParaCurveCase},
503 {CURVE_ARGS, [this](const char* key, const Json::Value& root, PiecewiseParameter& piecewiseParameter)
504 {
505 if (!root[key].isObject()) {
506 SkDebugf("curve_args is not object!");
507 return;
508 }
509 ParseSymbolCurveArgs(root[key], piecewiseParameter.curveArgs);
510 }
511 },
512 {DURATION, PiecewiseParaDurationCase},
513 {DELAY, PiecewiseParaDelayCase},
514 {"properties", [this](const char* key, const Json::Value& root, PiecewiseParameter& piecewiseParameter)
515 {
516 if (!root[key].isObject()) {
517 SkDebugf("properties is not object!");
518 return;
519 }
520 ParseSymbolProperties(root[key], piecewiseParameter.properties);
521 }
522 }
523 };
524
525 for (unsigned int i = 0; i < sizeof(tags) / sizeof(tags[0]); i++) {
526 key = tags[i].c_str();
527 if (!root.isMember(key)) {
528 continue;
529 }
530 if (funcMap.count(key) > 0) {
531 funcMap[key](key, root, piecewiseParameter);
532 }
533 }
534 }
535
ParseSymbolCurveArgs(const Json::Value & root,std::map<std::string,float> & curveArgs)536 void HmSymbolConfig_OHOS::ParseSymbolCurveArgs(const Json::Value& root, std::map<std::string, float>& curveArgs)
537 {
538 if (root.empty()) {
539 return;
540 }
541
542 for (Json::Value::const_iterator iter = root.begin(); iter != root.end(); ++iter) {
543 std::string name = iter.name();
544 const char* memberName = name.c_str();
545 if (!root[memberName].isNumeric()) {
546 SkDebugf("%{public}s is not numeric!", memberName);
547 continue;
548 }
549 curveArgs.insert({std::string(memberName), root[memberName].asFloat()});
550 }
551 }
552
ParseSymbolProperties(const Json::Value & root,std::map<std::string,std::vector<float>> & properties)553 void HmSymbolConfig_OHOS::ParseSymbolProperties(const Json::Value& root,
554 std::map<std::string, std::vector<float>>& properties)
555 {
556 for (Json::Value::const_iterator iter = root.begin(); iter != root.end(); ++iter) {
557 std::string name = iter.name();
558 const char* memberName = name.c_str();
559 if (!root[memberName].isArray()) {
560 SkDebugf("%{public}s is not array!", memberName);
561 continue;
562 }
563
564 std::vector<float> propertyValues;
565 for (unsigned int i = 0; i < root[memberName].size(); i++) {
566 if (!root[memberName][i].isNumeric()) {
567 SkDebugf("property value is not numeric!");
568 continue;
569 }
570 propertyValues.push_back(root[memberName][i].asFloat());
571 }
572
573 properties.insert({std::string(memberName), propertyValues});
574 }
575 }
576
ParseSymbolLayersGrouping(const Json::Value & root)577 void HmSymbolConfig_OHOS::ParseSymbolLayersGrouping(const Json::Value& root)
578 {
579 std::unordered_map<uint16_t, SymbolLayersGroups>* hmSymbolConfig
580 = &hmSymbolConfig_;
581 for (unsigned int i = 0; i < root.size(); i++) {
582 if (!root[i].isObject()) {
583 SkDebugf("symbol_layers_grouping[%{public}d] is not object!", i);
584 continue;
585 }
586 ParseOneSymbol(root[i], hmSymbolConfig);
587 }
588 }
589
SymbolGlyphCase(const char * key,const Json::Value & root,SymbolLayersGroups & symbolLayersGroups)590 static void SymbolGlyphCase(const char* key, const Json::Value& root, SymbolLayersGroups& symbolLayersGroups)
591 {
592 if (!root[key].isInt()) {
593 SkDebugf("symbol_glyph_id is not int!");
594 return;
595 }
596 symbolLayersGroups.symbolGlyphId = root[key].asInt();
597 }
598
ParseOneSymbolNativeCase(const char * key,const Json::Value & root,SymbolLayersGroups & symbolLayersGroups,uint16_t & nativeGlyphId)599 void HmSymbolConfig_OHOS::ParseOneSymbolNativeCase(const char* key, const Json::Value& root,
600 SymbolLayersGroups& symbolLayersGroups, uint16_t& nativeGlyphId)
601 {
602 if (!root[key].isInt()) {
603 SkDebugf("native_glyph_id is not int!");
604 return;
605 }
606 nativeGlyphId = root[key].asInt();
607 }
608
ParseOneSymbolLayerCase(const char * key,const Json::Value & root,SymbolLayersGroups & symbolLayersGroups)609 void HmSymbolConfig_OHOS::ParseOneSymbolLayerCase(const char* key, const Json::Value& root,
610 SymbolLayersGroups& symbolLayersGroups)
611 {
612 if (!root[key].isArray()) {
613 SkDebugf("layers is not array!");
614 return;
615 }
616 ParseLayers(root[key], symbolLayersGroups.layers);
617 }
618
ParseOneSymbolRenderCase(const char * key,const Json::Value & root,SymbolLayersGroups & symbolLayersGroups)619 void HmSymbolConfig_OHOS::ParseOneSymbolRenderCase(const char* key, const Json::Value& root,
620 SymbolLayersGroups& symbolLayersGroups)
621 {
622 if (!root[key].isArray()) {
623 SkDebugf("render_modes is not array!");
624 return;
625 }
626 ParseRenderModes(root[key], symbolLayersGroups.renderModeGroups);
627 }
628
ParseOneSymbolAnimateCase(const char * key,const Json::Value & root,SymbolLayersGroups & symbolLayersGroups)629 void HmSymbolConfig_OHOS::ParseOneSymbolAnimateCase(const char* key, const Json::Value& root,
630 SymbolLayersGroups& symbolLayersGroups)
631 {
632 if (!root[key].isArray()) {
633 SkDebugf("animation_settings is not array!");
634 return;
635 }
636 ParseAnimationSettings(root[key], symbolLayersGroups.animationSettings);
637 }
638
ParseOneSymbol(const Json::Value & root,std::unordered_map<uint16_t,SymbolLayersGroups> * hmSymbolConfig)639 void HmSymbolConfig_OHOS::ParseOneSymbol(const Json::Value& root,
640 std::unordered_map<uint16_t, SymbolLayersGroups>* hmSymbolConfig)
641 {
642 const char* key = nullptr;
643 std::string tags[] = {NATIVE_GLYPH_ID, SYMBOL_GLYPH_ID, LAYERS, RENDER_MODES, "animation_settings"};
644 uint16_t nativeGlyphId;
645 SymbolLayersGroups symbolLayersGroups;
646
647 SymbolKeyFuncMap funcMap = {
648 {NATIVE_GLYPH_ID, [this, &nativeGlyphId](const char* key, const Json::Value& root,
649 SymbolLayersGroups& symbolLayersGroups)
650 {
651 ParseOneSymbolNativeCase(key, root, symbolLayersGroups, nativeGlyphId);
652 }
653 },
654 {SYMBOL_GLYPH_ID, SymbolGlyphCase},
655 {LAYERS, [this](const char* key, const Json::Value& root, SymbolLayersGroups& symbolLayersGroups)
656 {
657 ParseOneSymbolLayerCase(key, root, symbolLayersGroups);
658 }
659 },
660 {RENDER_MODES, [this](const char* key, const Json::Value& root, SymbolLayersGroups& symbolLayersGroups)
661 {
662 ParseOneSymbolRenderCase(key, root, symbolLayersGroups);
663 }
664 },
665 {"animation_settings", [this](const char* key, const Json::Value& root,
666 SymbolLayersGroups& symbolLayersGroups)
667 {
668 ParseOneSymbolAnimateCase(key, root, symbolLayersGroups);
669 }
670 }
671 };
672 for (unsigned int i = 0; i < sizeof(tags) / sizeof(tags[0]); i++) {
673 key = tags[i].c_str();
674 if (!root.isMember(key)) {
675 continue;
676 }
677 if (funcMap.count(key) > 0) {
678 funcMap[key](key, root, symbolLayersGroups);
679 }
680 }
681 hmSymbolConfig->insert({nativeGlyphId, symbolLayersGroups});
682 }
683
ParseLayers(const Json::Value & root,std::vector<std::vector<size_t>> & layers)684 void HmSymbolConfig_OHOS::ParseLayers(const Json::Value& root, std::vector<std::vector<size_t>>& layers)
685 {
686 const char* key = "components";
687 for (unsigned int i = 0; i < root.size(); i++) {
688 if (!root[i].isObject()) {
689 SkDebugf("layer is not object!");
690 continue;
691 }
692
693 if (!root[i].isMember(key)) {
694 continue;
695 }
696 if (!root[i][key].isArray()) {
697 SkDebugf("components is not array!");
698 continue;
699 }
700 std::vector<size_t> components;
701 ParseComponets(root[i][key], components);
702 layers.push_back(components);
703 }
704 }
705
ParseComponets(const Json::Value & root,std::vector<size_t> & components)706 void HmSymbolConfig_OHOS::ParseComponets(const Json::Value& root, std::vector<size_t>& components)
707 {
708 for (unsigned int i = 0; i < root.size(); i++) {
709 if (!root[i].isInt()) {
710 SkDebugf("component is not int!");
711 continue;
712 }
713 components.push_back(root[i].asInt());
714 }
715 }
716
ParseRenderModes(const Json::Value & root,std::map<SymbolRenderingStrategy,std::vector<RenderGroup>> & renderModesGroups)717 void HmSymbolConfig_OHOS::ParseRenderModes(const Json::Value& root, std::map<SymbolRenderingStrategy,
718 std::vector<RenderGroup>>& renderModesGroups)
719 {
720 std::unordered_map<std::string, SymbolRenderingStrategy> strategeMap = {
721 {"monochrome", SymbolRenderingStrategy::SINGLE},
722 {"multicolor", SymbolRenderingStrategy::MULTIPLE_COLOR},
723 {"hierarchical", SymbolRenderingStrategy::MULTIPLE_OPACITY},
724 };
725 for (unsigned int i = 0; i < root.size(); i++) {
726 if (!root[i].isObject()) {
727 SkDebugf("render_mode is not object!");
728 continue;
729 }
730
731 SymbolRenderingStrategy renderingStrategy;
732 std::vector<RenderGroup> renderGroups;
733 if (root[i].isMember(MODE)) {
734 if (!root[i][MODE].isString()) {
735 SkDebugf("mode is not string!");
736 continue;
737 }
738 std::string modeValue = root[i][MODE].asCString();
739 if (strategeMap.count(modeValue) > 0) {
740 renderingStrategy = strategeMap[modeValue];
741 } else {
742 SkDebugf("%{public}s is invalid value!", modeValue.c_str());
743 continue;
744 }
745 }
746 if (root[i].isMember(RENDER_GROUPS)) {
747 if (!root[i][RENDER_GROUPS].isArray()) {
748 SkDebugf("render_groups is not array!");
749 continue;
750 }
751 ParseRenderGroups(root[i][RENDER_GROUPS], renderGroups);
752 }
753 renderModesGroups.insert({renderingStrategy, renderGroups});
754 }
755 }
756
ParseRenderGroups(const Json::Value & root,std::vector<RenderGroup> & renderGroups)757 void HmSymbolConfig_OHOS::ParseRenderGroups(const Json::Value& root, std::vector<RenderGroup>& renderGroups)
758 {
759 for (unsigned int i = 0; i < root.size(); i++) {
760 if (!root[i].isObject()) {
761 SkDebugf("render_group is not object!");
762 continue;
763 }
764
765 RenderGroup renderGroup;
766 if (root[i].isMember(GROUP_INDEXES) && root[i][GROUP_INDEXES].isArray()) {
767 ParseGroupIndexes(root[i][GROUP_INDEXES], renderGroup.groupInfos);
768 }
769 if (root[i].isMember(DEFAULT_COLOR) && root[i][DEFAULT_COLOR].isString()) {
770 ParseDefaultColor(root[i][DEFAULT_COLOR].asCString(), renderGroup);
771 }
772 if (root[i].isMember(FIX_ALPHA) && root[i][FIX_ALPHA].isDouble()) {
773 renderGroup.color.a = root[i][FIX_ALPHA].asFloat();
774 }
775 renderGroups.push_back(renderGroup);
776 }
777 }
778
ParseGroupIndexes(const Json::Value & root,std::vector<GroupInfo> & groupInfos)779 void HmSymbolConfig_OHOS::ParseGroupIndexes(const Json::Value& root, std::vector<GroupInfo>& groupInfos)
780 {
781 for (unsigned int i = 0; i < root.size(); i++) {
782 GroupInfo groupInfo;
783 if (root[i].isMember(LAYER_INDEXES)) {
784 if (!root[i][LAYER_INDEXES].isArray()) {
785 SkDebugf("layer_indexes is not array!");
786 continue;
787 }
788 ParseLayerOrMaskIndexes(root[i][LAYER_INDEXES], groupInfo.layerIndexes);
789 }
790 if (root[i].isMember(MASK_INDEXES)) {
791 if (!root[i][MASK_INDEXES].isArray()) {
792 SkDebugf("mask_indexes is not array!");
793 continue;
794 }
795 ParseLayerOrMaskIndexes(root[i][MASK_INDEXES], groupInfo.maskIndexes);
796 }
797 groupInfos.push_back(groupInfo);
798 }
799 }
800
ParseLayerOrMaskIndexes(const Json::Value & root,std::vector<size_t> & indexes)801 void HmSymbolConfig_OHOS::ParseLayerOrMaskIndexes(const Json::Value& root, std::vector<size_t>& indexes)
802 {
803 for (unsigned int i = 0; i < root.size(); i++) {
804 if (!root[i].isInt()) {
805 SkDebugf("index is not int!");
806 continue;
807 }
808 indexes.push_back(root[i].asInt());
809 }
810 }
811
ParseDefaultColor(const char * defaultColorStr,RenderGroup & renderGroup)812 void HmSymbolConfig_OHOS::ParseDefaultColor(const char* defaultColorStr, RenderGroup& renderGroup)
813 {
814 char defaultColorHex[defaultColorHexLen];
815 defaultColorHex[0] = '0';
816 defaultColorHex[1] = 'X';
817 if (strlen(defaultColorStr) == defaultColorStrLen) {
818 for (unsigned int i = 1; i < defaultColorStrLen; i++) {
819 defaultColorHex[i + 1] = defaultColorStr[i];
820 }
821 defaultColorHex[defaultColorHexLen - 1] = '\0';
822 } else {
823 SkDebugf("%{public}s is invalid value!", defaultColorStr);
824 return;
825 }
826
827 char* endPtr = nullptr;
828 int defaultColorInt = strtol(defaultColorHex, &endPtr, hexFlag);
829 renderGroup.color.r = (defaultColorInt >> twoBytesBitsLen) & 0xFF;
830 renderGroup.color.g = (defaultColorInt >> oneByteBitsLen) & 0xFF;
831 renderGroup.color.b = defaultColorInt & 0xFF;
832 }
833
ParseAnimationSettings(const Json::Value & root,std::vector<AnimationSetting> & animationSettings)834 void HmSymbolConfig_OHOS::ParseAnimationSettings(const Json::Value& root,
835 std::vector<AnimationSetting>& animationSettings)
836 {
837 for (unsigned int i = 0; i < root.size(); i++) {
838 if (!root[i].isObject()) {
839 SkDebugf("animation_setting is not object!");
840 continue;
841 }
842 AnimationSetting animationSetting;
843 ParseAnimationSetting(root[i], animationSetting);
844 animationSettings.push_back(animationSetting);
845 }
846 }
847
ParseAnimationSetting(const Json::Value & root,AnimationSetting & animationSetting)848 void HmSymbolConfig_OHOS::ParseAnimationSetting(const Json::Value& root, AnimationSetting& animationSetting)
849 {
850 if (root.isMember(ANIMATION_TYPES) && root[ANIMATION_TYPES].isArray()) {
851 ParseAnimationTypes(root[ANIMATION_TYPES], animationSetting.animationTypes);
852 }
853
854 if (root.isMember(GROUP_SETTINGS) && root[GROUP_SETTINGS].isArray()) {
855 ParseGroupSettings(root[GROUP_SETTINGS], animationSetting.groupSettings);
856 }
857 }
858
ParseAnimationTypes(const Json::Value & root,std::vector<AnimationType> & animationTypes)859 void HmSymbolConfig_OHOS::ParseAnimationTypes(const Json::Value& root, std::vector<AnimationType>& animationTypes)
860 {
861 for (unsigned int i = 0; i < root.size(); i++) {
862 if (!root[i].isString()) {
863 SkDebugf("animation_types is not string!");
864 continue;
865 }
866 const std::string animationTypeStr = root[i].asCString();
867 AnimationType animationType;
868 ParseAnimationType(animationTypeStr, animationType);
869 animationTypes.push_back(animationType);
870 }
871 }
872
ParseAnimationType(const std::string & animationTypeStr,AnimationType & animationType)873 void HmSymbolConfig_OHOS::ParseAnimationType(const std::string& animationTypeStr, AnimationType& animationType)
874 {
875 auto iter = ANIMATIONS_TYPES.find(animationTypeStr);
876 if (iter != ANIMATIONS_TYPES.end()) {
877 animationType = iter->second;
878 } else {
879 SkDebugf("%{public}s is invalid value!", animationTypeStr.c_str());
880 }
881 }
882
ParseGroupSettings(const Json::Value & root,std::vector<GroupSetting> & groupSettings)883 void HmSymbolConfig_OHOS::ParseGroupSettings(const Json::Value& root, std::vector<GroupSetting>& groupSettings)
884 {
885 for (unsigned int i = 0; i < root.size(); i++) {
886 if (!root[i].isObject()) {
887 SkDebugf("group_setting is not object!");
888 continue;
889 }
890 GroupSetting groupSetting;
891 ParseGroupSetting(root[i], groupSetting);
892 groupSettings.push_back(groupSetting);
893 }
894 }
895
ParseGroupSetting(const Json::Value & root,GroupSetting & groupSetting)896 void HmSymbolConfig_OHOS::ParseGroupSetting(const Json::Value& root, GroupSetting& groupSetting)
897 {
898 if (root.isMember(GROUP_INDEXES)) {
899 if (!root[GROUP_INDEXES].isArray()) {
900 SkDebugf("group_indexes is not array!");
901 } else {
902 ParseGroupIndexes(root[GROUP_INDEXES], groupSetting.groupInfos);
903 }
904 }
905
906 if (root.isMember(ANIMATION_INDEX)) {
907 if (!root[ANIMATION_INDEX].isInt()) {
908 SkDebugf("animation_index is not int!");
909 } else {
910 groupSetting.animationIndex = root[ANIMATION_INDEX].asInt();
911 }
912 }
913 }