• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }