• 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 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 }