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