• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "frameworks/core/components_ng/svg/parse/svg_attributes_parser.h"
17 #include "core/common/container.h"
18 namespace OHOS::Ace::NG {
19 namespace {
20 const char LINECAP_ROUND[] = "round";
21 const char LINECAP_SQUARE[] = "square";
22 const char LINEJOIN_BEVEL[] = "bevel";
23 const char LINEJOIN_ROUND[] = "round";
24 const std::regex COLOR_WITH_ALPHA(
25     R"(rgba?\(([0-9]{1,3})\,([0-9]{1,3})\,([0-9]{1,3})\,(\d+\.?\d*)\))", std::regex::icase);
26 const std::regex COLOR_WITH_RGBA_MAGIC("#[0-9A-Fa-f]{7,8}");
27 const std::regex COLOR_FORMAT_FOUR_HEX("#[0-9A-Fa-f]{4}");
28 constexpr int32_t RADIX_HEX = 16;
29 constexpr int32_t THREE_BYTE_BITS = 24;
30 constexpr int32_t TWO_BYTE_BITS = 16;
31 constexpr int32_t TWELVE_BITS = 12;
32 constexpr int32_t ONE_BYTE_BITS = 8;
33 constexpr int32_t FOUR_BITS = 4;
34 constexpr uint32_t RGBA_SUB_MATCH_SIZE = 5;
35 constexpr int32_t HEX_COLOR_LEN_SEVEN = 7;
36 constexpr double MAX_ALPHA = 1.0;
37 constexpr Dimension TRANSFORM_ORIGIN_DEFAULT = 0.5_pct;
38 constexpr size_t TRANSFORM_ORIGIN_PARA_AMOUNT1 = 1;
39 constexpr size_t TRANSFORM_ORIGIN_PARA_AMOUNT2 = 2;
40 constexpr size_t TRANSFORM_ORIGIN_PARA_AMOUNT3 = 3;
41 const char TRANSFORM_MATRIX[] = "matrix";
42 const char TRANSFORM_ROTATE[] = "rotate";
43 const char TRANSFORM_SCALE[] = "scale";
44 const char TRANSFORM_SKEWX[] = "skewX";
45 const char TRANSFORM_SKEWY[] = "skewY";
46 const char TRANSFORM_TRANSLATE[] = "translate";
47 const char SVG_ALIGN_XMIN_YMIN[] = "xMinYMin";
48 const char SVG_ALIGN_XMIN_YMID[] = "xMinYMid";
49 const char SVG_ALIGN_XMIN_YMAX[] = "xMinYMax";
50 const char SVG_ALIGN_XMID_YMIN[] = "xMidYMin";
51 const char SVG_ALIGN_XMID_YMID[] = "xMidYMid";
52 const char SVG_ALIGN_XMID_YMAX[] = "xMidYMax";
53 const char SVG_ALIGN_XMAX_YMIN[] = "xMaxYMin";
54 const char SVG_ALIGN_XMAX_YMID[] = "xMaxYMid";
55 const char SVG_ALIGN_XMAX_YMAX[] = "xMaxYMax";
56 const char SVG_ALIGN_NONE[] = "none";
57 const char SVG_ALIGN_MEET[] = "meet";
58 const char SVG_ALIGN_SLICE[] = "slice";
59 constexpr float PERCENT_RANGE_MAX = 100.0;
60 }
61 
GetLineCapStyle(const std::string & val)62 LineCapStyle SvgAttributesParser::GetLineCapStyle(const std::string& val)
63 {
64     if (val == LINECAP_ROUND) {
65         return LineCapStyle::ROUND;
66     } else if (val == LINECAP_SQUARE) {
67         return LineCapStyle::SQUARE;
68     } else {
69         return LineCapStyle::BUTT;
70     }
71 }
72 
GetLineJoinStyle(const std::string & val)73 LineJoinStyle SvgAttributesParser::GetLineJoinStyle(const std::string& val)
74 {
75     if (val == LINEJOIN_BEVEL) {
76         return LineJoinStyle::BEVEL;
77     } else if (val == LINEJOIN_ROUND) {
78         return LineJoinStyle::ROUND;
79     } else {
80         return LineJoinStyle::MITER;
81     }
82 }
83 
GetSpecialColor(const std::string & value)84 std::optional<Color> SvgAttributesParser::GetSpecialColor(const std::string& value)
85 {
86     static const LinearMapNode<Color> COLOR_TABLE[] = {
87         { "aliceblue", Color(0xfff0f8ff) },
88         { "antiquewhite", Color(0xfffaebd7) },
89         { "aqua", Color(0xff00ffff) },
90         { "aquamarine", Color(0xff7fffd4) },
91         { "azure", Color(0xfff0ffff) },
92         { "beige", Color(0xfff5f5dc) },
93         { "bisque", Color(0xffffe4c4) },
94         { "black", Color(0XFF000000) },
95         { "blanchedalmond", Color(0xffffebcd) },
96         { "blue", Color(0xff0000ff) },
97         { "blueviolet", Color(0xff8a2be2) },
98         { "brown", Color(0xffa52a2a) },
99         { "burlywood", Color(0xffdeb887) },
100         { "cadetblue", Color(0xff5f9ea0) },
101         { "chartreuse", Color(0xff7fff00) },
102         { "chocolate", Color(0xffd2691e) },
103         { "coral", Color(0xffff7f50) },
104         { "cornflowerblue", Color(0xff6495ed) },
105         { "cornsilk", Color(0xfffff8dc) },
106         { "crimson", Color(0xffdc143c) },
107         { "cyan", Color(0xff00ffff) },
108         { "darkblue", Color(0xff00008b) },
109         { "darkcyan", Color(0xff008b8b) },
110         { "darkgoldenrod", Color(0xffb8860b) },
111         { "darkgray", Color(0xffa9a9a9) },
112         { "darkgreen", Color(0xff006400) },
113         { "darkgrey", Color(0xffa9a9a9) },
114         { "darkkhaki", Color(0xffbdb76b) },
115         { "darkmagenta", Color(0xff8b008b) },
116         { "darkolivegreen", Color(0xff556b2f) },
117         { "darkorange", Color(0xffff8c00) },
118         { "darkorchid", Color(0xff9932cc) },
119         { "darkred", Color(0xff8b0000) },
120         { "darksalmon", Color(0xffe9967a) },
121         { "darkseagreen", Color(0xff8fbc8f) },
122         { "darkslateblue", Color(0xff483d8b) },
123         { "darkslategray", Color(0xff2f4f4f) },
124         { "darkslategrey", Color(0xff2f4f4f) },
125         { "darkturquoise", Color(0xff00ced1) },
126         { "darkviolet", Color(0xff9400D3) },
127         { "deeppink", Color(0xffff1493) },
128         { "deepskyblue", Color(0xff00bfff) },
129         { "dimgray", Color(0xff696969) },
130         { "dimgrey", Color(0xff696969) },
131         { "dodgerblue", Color(0xff1e90ff) },
132         { "firebrick", Color(0xffb22222) },
133         { "floralwhite", Color(0xfffffaf0) },
134         { "forestgreen", Color(0xff228b22) },
135         { "fuchsia", Color(0xffff00ff) },
136         { "gainsboro", Color(0xffdcdcdc) },
137         { "ghostwhite", Color(0xfff8f8ff) },
138         { "gold", Color(0xffffd700) },
139         { "goldenrod", Color(0xffdaa520) },
140         { "gray", Color(0xff808080) },
141         { "green", Color(0xff008000) },
142         { "greenyellow", Color(0xffadff2f) },
143         { "grey", Color(0xff808080) },
144         { "honeydew", Color(0xfff0fff0) },
145         { "hotpink", Color(0xffff69b4) },
146         { "indianred", Color(0xffcd5c5c) },
147         { "indigo", Color(0xff4b0082) },
148         { "ivory", Color(0xfffffff0) },
149         { "khaki", Color(0xfff0e68c) },
150         { "lavender", Color(0xffe6e6fa) },
151         { "lavenderblush", Color(0xfffff0f5) },
152         { "lawngreen", Color(0xff7cfc00) },
153         { "lemonchiffon", Color(0xfffffacd) },
154         { "lightblue", Color(0xffadd8e6) },
155         { "lightcoral", Color(0xfff08080) },
156         { "lightcyan", Color(0xffe0ffff) },
157         { "lightgoldenrodyellow", Color(0xfffafad2) },
158         { "lightgray", Color(0xffd3d3d3) },
159         { "lightgreen", Color(0xff90ee90) },
160         { "lightgrey", Color(0xffd3d3d3) },
161         { "lightpink", Color(0xffffb6c1) },
162         { "lightsalmon", Color(0xffffa07a) },
163         { "lightseagreen", Color(0xff20b2aa) },
164         { "lightskyblue", Color(0xff87cefa) },
165         { "lightslategray", Color(0xff778899) },
166         { "lightslategrey", Color(0xff778899) },
167         { "lightsteelblue", Color(0xffb0c4de) },
168         { "lightyellow", Color(0xffffffe0) },
169         { "lime", Color(0xff00ff00) },
170         { "limegreen", Color(0xff32cd32) },
171         { "linen", Color(0xfffaf0e6) },
172         { "magenta", Color(0xffff00ff) },
173         { "maroon", Color(0xff800000) },
174         { "mediumaquamarine", Color(0xff66cdaa) },
175         { "mediumblue", Color(0xff0000cd) },
176         { "mediumorchid", Color(0xffba55d3) },
177         { "mediumpurple", Color(0xff9370db) },
178         { "mediumseagreen", Color(0xff3cb371) },
179         { "mediumslateblue", Color(0xff7b68ee) },
180         { "mediumspringgreen", Color(0xff00fa9a) },
181         { "mediumturquoise", Color(0xff48d1cc) },
182         { "mediumvioletred", Color(0xffc71585) },
183         { "midnightblue", Color(0xff191970) },
184         { "mintcream", Color(0xfff5fffa) },
185         { "mistyrose", Color(0xffffe4e1) },
186         { "moccasin", Color(0xffffe4b5) },
187         { "navajowhite", Color(0xffffdead) },
188         { "navy", Color(0xff000080) },
189         { "oldlace", Color(0xfffdf5e6) },
190         { "olive", Color(0xff808000) },
191         { "olivedrab", Color(0xff6b8e23) },
192         { "orange", Color(0xffffa500) },
193         { "orangered", Color(0xffff4500) },
194         { "orchid", Color(0xffda70d6) },
195         { "palegoldenrod", Color(0xffeee8aa) },
196         { "palegreen", Color(0xff98fb98) },
197         { "paleturquoise", Color(0xffafeeee) },
198         { "palevioletred", Color(0xffdb7093) },
199         { "papayawhip", Color(0xffffefd5) },
200         { "peachpuff", Color(0xffffdab9) },
201         { "peru", Color(0xffcd853f) },
202         { "pink", Color(0xffffc0cb) },
203         { "plum", Color(0xffdda0dd) },
204         { "powderblue", Color(0xffb0e0e6) },
205         { "purple", Color(0xff800080) },
206         { "red", Color(0xffff0000) },
207         { "rosybrown", Color(0xffbc8f8f) },
208         { "royalblue", Color(0xff4169e1) },
209         { "rebeccapurple", Color(0xff663399) },
210         { "saddlebrown", Color(0xff8b4513) },
211         { "salmon", Color(0xfffa8072) },
212         { "sandybrown", Color(0xfff4a460) },
213         { "seagreen", Color(0xff2e8b57) },
214         { "seashell", Color(0xfffff5ee) },
215         { "sienna", Color(0xffa0522d) },
216         { "silver", Color(0xffc0c0c0) },
217         { "skyblue", Color(0xff87ceeb) },
218         { "slateblue", Color(0xff6a5acd) },
219         { "slategray", Color(0xff708090) },
220         { "slategrey", Color(0xff708090) },
221         { "snow", Color(0xfffffafa) },
222         { "springgreen", Color(0xff00ff7f) },
223         { "steelblue", Color(0xff4682b4) },
224         { "tan", Color(0xffd2b48c) },
225         { "teal", Color(0xff008080) },
226         { "thistle", Color(0xffd8bfd8) },
227         { "tomato", Color(0xffff6347) },
228         { "turquoise", Color(0xff40e0d0) },
229         { "violet", Color(0xffee82ee) },
230         { "wheat", Color(0xfff5deb3) },
231         { "white", Color(0xffffffff) },
232         { "whitesmoke", Color(0xfff5f5f5) },
233         { "yellow", Color(0xffffff00) },
234         { "yellowgreen", Color(0xff9acd32) },
235     };
236     int64_t colorIndex = BinarySearchFindIndex(COLOR_TABLE, ArraySize(COLOR_TABLE), value.c_str());
237     if (colorIndex != -1) {
238         return COLOR_TABLE[colorIndex].value;
239     }
240     return std::nullopt;
241 }
242 
ParseRGBAMagicColor(const std::string & value,Color & color)243 bool SvgAttributesParser::ParseRGBAMagicColor(const std::string& value, Color& color)
244 {
245     std::smatch matches;
246     // #RGBA--->RRGGBBAA
247     if (std::regex_match(value, matches, COLOR_FORMAT_FOUR_HEX)) {
248         auto colorStr = value.substr(1);
249         color = GetColorFrom4HexString(colorStr);
250         return true;
251     }
252 
253     if (!std::regex_match(value, matches, COLOR_WITH_RGBA_MAGIC)) {
254         return false;
255     }
256     std::string colorStr = value.substr(1);
257     // #00ffaad--->default black
258     if (colorStr.length() == HEX_COLOR_LEN_SEVEN) {
259         color = Color::BLACK;
260         return true;
261     }
262     // #00ffaadd
263     color = GetColorFromHexString(colorStr);
264     return true;
265 }
266 
ParseColor(std::string value,Color & color)267 bool SvgAttributesParser::ParseColor(std::string value, Color& color)
268 {
269     auto colorOpt = GetSpecialColor(value);
270     if (colorOpt.has_value()) {
271         color = colorOpt.value();
272         return true;
273     }
274     value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
275     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)
276         && ParseRGBAMagicColor(value, color)) {
277         return true;
278     }
279     if (Color::MatchColorHexString(value)) {
280         color = Color::FromString(value);
281         return true;
282     }
283     return false;
284 }
285 
GetColor(const std::string & value)286 Color SvgAttributesParser::GetColor(const std::string& value)
287 {
288     auto colorOpt = GetSpecialColor(value);
289     if (colorOpt.has_value()) {
290         return colorOpt.value();
291     }
292     return Color::FromString(value);
293 }
294 
ParseDimension(const std::string & value,bool useVp)295 Dimension SvgAttributesParser::ParseDimension(const std::string& value, bool useVp)
296 {
297     return StringUtils::StringToDimension(value, useVp);
298 }
299 
StringToDimensionWithUnitSvg(const std::string & value,Dimension & dimension)300 void SvgAttributesParser::StringToDimensionWithUnitSvg(const std::string& value, Dimension& dimension)
301 {
302     errno = 0;
303     if (std::strcmp(value.c_str(), "auto") == 0) {
304         return;
305     }
306     char* pEnd = nullptr;
307     double result = std::strtod(value.c_str(), &pEnd);
308     if ((pEnd == nullptr) || (pEnd == value.c_str()) || (errno == ERANGE)) {
309         return;
310     }
311     if (std::strcmp(pEnd, "%") == 0) {
312         // Parse percent, transfer from [0, 100] to [0, 1]
313         dimension = Dimension(result / PERCENT_RANGE_MAX, DimensionUnit::PERCENT);
314     } else if (std::strcmp(pEnd, "px") == 0) {
315         dimension = Dimension(result, DimensionUnit::PX);
316     } else if (std::strcmp(pEnd, "vp") == 0) {
317         dimension = Dimension(result, DimensionUnit::VP);
318     } else if (std::strcmp(pEnd, "fp") == 0) {
319         dimension = Dimension(result, DimensionUnit::FP);
320     } else if (std::strcmp(pEnd, "lpx") == 0) {
321         dimension = Dimension(result, DimensionUnit::LPX);
322     } else if (std::strcmp(pEnd, "\0") == 0) {
323         dimension = Dimension(result, DimensionUnit::PX);
324     }
325 }
326 
ParseDimension(const std::string & value,Dimension & dimension,bool useVp)327 void SvgAttributesParser::ParseDimension(const std::string& value, Dimension& dimension, bool useVp)
328 {
329     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
330         dimension = StringUtils::StringToDimension(value, useVp);
331         return;
332     }
333     StringToDimensionWithUnitSvg(value, dimension);
334 }
335 
ParseDouble(const std::string & value)336 double SvgAttributesParser::ParseDouble(const std::string& value)
337 {
338     return StringUtils::StringToDouble(value);
339 }
340 
CheckColorAlpha(const std::string & colorStr,Color & result)341 bool SvgAttributesParser::CheckColorAlpha(const std::string& colorStr, Color& result)
342 {
343     std::smatch matches;
344     if (std::regex_match(colorStr, matches, COLOR_WITH_ALPHA)) {
345         if (matches.size() == RGBA_SUB_MATCH_SIZE) {
346             auto red = static_cast<uint8_t>(std::stoi(matches[1]));
347             auto green = static_cast<uint8_t>(std::stoi(matches[2]));
348             auto blue = static_cast<uint8_t>(std::stoi(matches[3]));
349             auto alpha = static_cast<double>(std::stod(matches[4]));
350             // Scale up from 0~1.0 to 255
351             result = Color::FromARGB(static_cast<uint8_t>(std::min(MAX_ALPHA, alpha)) * 0xff, red, green, blue);
352             return true;
353         }
354     }
355     return false;
356 }
357 
GetTransformOrigin(const std::string & transformOrigin)358 std::pair<Dimension, Dimension> SvgAttributesParser::GetTransformOrigin(const std::string& transformOrigin)
359 {
360     if (transformOrigin.empty()) {
361         return std::pair<Dimension, Dimension>(0, 0);
362     }
363     std::vector<std::string> valueVector;
364     Dimension pivotX = Dimension(0.0);
365     Dimension pivotY = Dimension(0.0);
366     Dimension tempPivotX = Dimension(0.0);
367     Dimension tempPivotY = Dimension(0.0);
368     StringUtils::StringSplitter(transformOrigin, ' ', valueVector);
369     if (valueVector.size() == TRANSFORM_ORIGIN_PARA_AMOUNT1) {
370         if (StringUtils::StringToDimensionWithUnitNG(valueVector[0], tempPivotX)) {
371             pivotX = tempPivotX;
372             pivotY = TRANSFORM_ORIGIN_DEFAULT;
373             TAG_LOGI(AceLogTag::ACE_IMAGE, "GetTransformOrigin value:%{public}s|%{public}s",
374                 pivotX.ToString().c_str(), pivotY.ToString().c_str());
375         }
376     } else if ((valueVector.size() == TRANSFORM_ORIGIN_PARA_AMOUNT2) ||
377                (valueVector.size() == TRANSFORM_ORIGIN_PARA_AMOUNT3)) {
378         if (StringUtils::StringToDimensionWithUnitNG(valueVector[0], tempPivotX) &&
379             StringUtils::StringToDimensionWithUnitNG(valueVector[1], tempPivotY)) {
380             pivotX = tempPivotX;
381             pivotY = tempPivotY;
382             TAG_LOGI(AceLogTag::ACE_IMAGE, "GetTransformOrigin value:%{public}s|%{public}s",
383                 pivotX.ToString().c_str(), pivotY.ToString().c_str());
384         }
385     }
386     return std::pair<Dimension, Dimension>(pivotX, pivotY);
387 }
388 
IsBalanced(const std::string & str)389 bool IsBalanced(const std::string& str)
390 {
391     std::stack<char> bracketStack;
392     for (char ch : str) {
393         if (ch == '(') {
394             bracketStack.push(ch);
395         } else if (ch == ')') {
396             if (bracketStack.empty()) {
397                 return false;
398             } else if (bracketStack.top() != '(') {
399                 return false;
400             } else {
401                 bracketStack.pop();
402             }
403         }
404     }
405     return bracketStack.empty();
406 }
407 
IsLegalParam(const std::vector<std::string> & paramVec)408 bool IsLegalParam(const std::vector<std::string>& paramVec)
409 {
410     double result = 0.0;
411     for (auto param : paramVec) {
412         if (param.empty() || (param.back() == '%')) {
413             return false;
414         }
415         if (!StringUtils::StringToDouble(param, result)) {
416             return false;
417         }
418     }
419     return true;
420 }
421 
IsValidFuncType(const std::string & funcType)422 bool IsValidFuncType(const std::string& funcType)
423 {
424     if ((funcType == TRANSFORM_MATRIX) || (funcType == TRANSFORM_ROTATE) || (funcType == TRANSFORM_SCALE) ||
425         (funcType == TRANSFORM_SKEWX) || (funcType == TRANSFORM_SKEWY) || (funcType == TRANSFORM_TRANSLATE)) {
426         return true;
427     }
428     return false;
429 }
430 
GetTransformInfo(const std::string & transform)431 std::vector<NG::TransformInfo> SvgAttributesParser::GetTransformInfo(const std::string& transform)
432 {
433     std::vector<NG::TransformInfo> transformVec;
434     if (transform.empty() || !IsBalanced(transform)) {
435         return std::vector<NG::TransformInfo>();
436     }
437     std::string transformStr = StringUtils::TrimStr(transform);
438     if (transformStr.empty()) {
439         return std::vector<NG::TransformInfo>();
440     }
441     std::vector<std::string> attrs;
442     StringUtils::SplitStr(transformStr, ")", attrs);
443     for (auto& attr : attrs) {
444         attr = StringUtils::TrimStr(attr);
445         if (attr.empty()) {
446             continue;
447         }
448 
449         std::string funcType = attr.substr(0, attr.find_first_of("("));
450         if (funcType.empty()) {
451             return std::vector<NG::TransformInfo>();
452         }
453         funcType = StringUtils::TrimStr(funcType);
454         if (!IsValidFuncType(funcType)) {
455             return std::vector<NG::TransformInfo>();
456         }
457 
458         std::string parameters = attr.substr(attr.find_first_of("(") + 1);
459         if (parameters.empty()) {
460             return std::vector<NG::TransformInfo>();
461         }
462         parameters = StringUtils::TrimStr(parameters);
463 
464         std::vector<std::string> paramVec;
465         std::string tag = (parameters.find(",") != std::string::npos) ? "," : " ";
466         StringUtils::SplitStr(parameters, tag, paramVec);
467         if (paramVec.empty() || !IsLegalParam(paramVec)) {
468             return std::vector<NG::TransformInfo>();
469         }
470         NG::TransformInfo transformInfo {funcType, paramVec};
471         transformVec.push_back(transformInfo);
472     }
473     return transformVec;
474 }
475 
ParseSvgAlign(const std::string & value)476 SvgAlign SvgAttributesParser::ParseSvgAlign(const std::string& value)
477 {
478     static const LinearMapNode<SvgAlign> SVG_ALIGN_ARRAY[] = {
479         { SVG_ALIGN_NONE, SvgAlign::ALIGN_NONE },
480         { SVG_ALIGN_XMAX_YMAX, SvgAlign::ALIGN_XMAX_YMAX },
481         { SVG_ALIGN_XMAX_YMID, SvgAlign::ALIGN_XMAX_YMID },
482         { SVG_ALIGN_XMAX_YMIN, SvgAlign::ALIGN_XMAX_YMIN },
483         { SVG_ALIGN_XMID_YMAX, SvgAlign::ALIGN_XMID_YMAX },
484         { SVG_ALIGN_XMID_YMID, SvgAlign::ALIGN_XMID_YMID },
485         { SVG_ALIGN_XMID_YMIN, SvgAlign::ALIGN_XMID_YMIN },
486         { SVG_ALIGN_XMIN_YMAX, SvgAlign::ALIGN_XMIN_YMAX },
487         { SVG_ALIGN_XMIN_YMID, SvgAlign::ALIGN_XMIN_YMID },
488         { SVG_ALIGN_XMIN_YMIN, SvgAlign::ALIGN_XMIN_YMIN },
489     };
490     auto attrIter = BinarySearchFindIndex(SVG_ALIGN_ARRAY, ArraySize(SVG_ALIGN_ARRAY), value.c_str());
491     if (attrIter != -1) {
492         return SVG_ALIGN_ARRAY[attrIter].value;
493     }
494     return SvgAlign::ALIGN_XMID_YMID;
495 }
496 
ParseSvgMeetOrSlice(const std::string & value)497 SvgMeetOrSlice SvgAttributesParser::ParseSvgMeetOrSlice(const std::string& value)
498 {
499     static const LinearMapNode<SvgMeetOrSlice> SVG_MEETORSLICE_ARRAY[] = {
500         { SVG_ALIGN_MEET, SvgMeetOrSlice::MEET },
501         { SVG_ALIGN_SLICE, SvgMeetOrSlice::SLICE },
502     };
503     auto attrIter = BinarySearchFindIndex(SVG_MEETORSLICE_ARRAY, ArraySize(SVG_MEETORSLICE_ARRAY), value.c_str());
504     if (attrIter != -1) {
505         return SVG_MEETORSLICE_ARRAY[attrIter].value;
506     }
507     return SvgMeetOrSlice::MEET;
508 }
509 
ComputeTranslate(const Size & viewBox,const Size & viewPort,const float scaleX,const float scaleY,const SvgAlign & svgAlign,float & translateX,float & translateY)510 void SvgAttributesParser::ComputeTranslate(const Size& viewBox, const Size& viewPort, const float scaleX,
511     const float scaleY, const SvgAlign& svgAlign, float& translateX, float& translateY)
512 {
513     translateX = 0.0f;
514     translateY = 0.0f;
515     switch (svgAlign) {
516         /*translate x y eq 0.0f*/
517         case SvgAlign::ALIGN_XMIN_YMIN:
518             break;
519         /*translate x eq 0.0f*/
520         case SvgAlign::ALIGN_XMIN_YMID:
521             translateY = (viewPort.Height() - viewBox.Height() * scaleY) * HALF_FLOAT;
522             break;
523         /*translate x eq 0.0f*/
524         case SvgAlign::ALIGN_XMIN_YMAX:
525             translateY = viewPort.Height() - viewBox.Height() * scaleY;
526             break;
527         /*translate y eq 0.0f*/
528         case SvgAlign::ALIGN_XMID_YMIN:
529             translateX = (viewPort.Width() - viewBox.Width() * scaleX) * HALF_FLOAT;
530             break;
531         case SvgAlign::ALIGN_XMID_YMAX:
532             translateX = (viewPort.Width() - viewBox.Width() * scaleX) * HALF_FLOAT;
533             translateY = viewPort.Height() - viewBox.Height() * scaleY;
534             break;
535         /*translate y eq 0.0f*/
536         case SvgAlign::ALIGN_XMAX_YMIN:
537             translateX = viewPort.Width() - viewBox.Width() * scaleX;
538             break;
539         case SvgAlign::ALIGN_XMAX_YMID:
540             translateX = viewPort.Width() - viewBox.Width() * scaleX;
541             translateY = (viewPort.Height() - viewBox.Height() * scaleY) * HALF_FLOAT;
542             break;
543         case SvgAlign::ALIGN_XMAX_YMAX:
544             translateX = viewPort.Width() - viewBox.Width() * scaleX;
545             translateY = viewPort.Height() - viewBox.Height() * scaleY;
546             break;
547         case SvgAlign::ALIGN_XMID_YMID:
548         default:
549             translateX = (viewPort.Width() - viewBox.Width() * scaleX) * HALF_FLOAT;
550             translateY = (viewPort.Height() - viewBox.Height() * scaleY) * HALF_FLOAT;
551             break;
552     }
553 }
554 
ComputeScale(const Size & viewBox,const Size & viewPort,const SvgPreserveAspectRatio & preserveAspectRatio,float & scaleX,float & scaleY)555 void SvgAttributesParser::ComputeScale(const Size& viewBox, const Size& viewPort,
556     const SvgPreserveAspectRatio& preserveAspectRatio, float& scaleX, float& scaleY)
557 {
558     if (!viewBox.IsValid()) {
559         return;
560     }
561     float ratioX = viewPort.Width() / viewBox.Width();
562     float ratioY = viewPort.Height() / viewBox.Height();
563     if (preserveAspectRatio.svgAlign == SvgAlign::ALIGN_NONE) {
564         scaleX = ratioX;
565         scaleY = ratioY;
566         return;
567     }
568     switch (preserveAspectRatio.meetOrSlice) {
569         case SvgMeetOrSlice::SLICE:
570             scaleX = std::max(ratioX, ratioY);
571             break;
572         case SvgMeetOrSlice::MEET:
573         default:
574             scaleX = std::min(ratioX, ratioY);
575             break;
576     }
577     scaleY = scaleX;
578 }
579 
GetColorFromHexString(const std::string & value)580 Color SvgAttributesParser::GetColorFromHexString(const std::string& value)
581 {
582     auto colorInt32 = std::strtoul(value.c_str(), nullptr, RADIX_HEX);
583     auto red = (colorInt32 >> THREE_BYTE_BITS) & 0xff;
584     auto green = (colorInt32 >> TWO_BYTE_BITS) & 0xff;
585     auto blue = (colorInt32 >> ONE_BYTE_BITS) & 0xff;
586     auto alpha = colorInt32 & 0xff;
587     return Color::FromARGB(alpha, red, green, blue);
588 }
589 
GetColorFrom4HexString(const std::string & value)590 Color SvgAttributesParser::GetColorFrom4HexString(const std::string& value)
591 {
592     // value is rgba, convert to rrggbbaa color
593     auto colorInt32 = std::strtoul(value.c_str(), nullptr, RADIX_HEX);
594     auto red = (colorInt32 >> TWELVE_BITS) & 0xf;
595     red += red << FOUR_BITS;
596     auto green = (colorInt32 >> ONE_BYTE_BITS) & 0xf;
597     green += green << FOUR_BITS;
598     auto blue = (colorInt32 >> FOUR_BITS) & 0xf;
599     blue += blue << FOUR_BITS;
600     auto alpha = colorInt32 & 0xf;
601     alpha += alpha << FOUR_BITS;
602     return Color::FromARGB(alpha, red, green, blue);
603 }
604 } // namespace OHOS::Ace::NG
605