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