1 /*
2  * Copyright (c) 2021 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 "core/components/declaration/svg/svg_base_declaration.h"
17 
18 #include "base/utils/string_utils.h"
19 #include "core/components/declaration/common/declaration_constants.h"
20 #include "frameworks/bridge/common/utils/utils.h"
21 
22 namespace OHOS::Ace {
23 namespace {
24 
25 const char LINECAP_ROUND[] = "round";
26 const char LINECAP_SQUARE[] = "square";
27 const char LINEJOIN_BEVEL[] = "bevel";
28 const char LINEJOIN_ROUND[] = "round";
29 
30 const char DOM_SVG_SRC_FILL_OPACITY[] = "fill-opacity";
31 const char DOM_SVG_SRC_FILL_RULE[] = "fill-rule";
32 const char DOM_SVG_SRC_STROKE_DASHARRAY[] = "stroke-dasharray";
33 const char DOM_SVG_SRC_STROKE_DASHOFFSET[] = "stroke-dashoffset";
34 const char DOM_SVG_SRC_STROKE_LINECAP[] = "stroke-linecap";
35 const char DOM_SVG_SRC_STROKE_LINEJOIN[] = "stroke-linejoin";
36 const char DOM_SVG_SRC_STROKE_MITERLIMIT[] = "stroke-miterlimit";
37 const char DOM_SVG_SRC_STROKE_OPACITY[] = "stroke-opacity";
38 const char DOM_SVG_SRC_STROKE_WIDTH[] = "stroke-width";
39 const char DOM_SVG_SRC_CLIP_PATH[] = "clip-path";
40 const char DOM_SVG_SRC_CLIP_RULE[] = "clip-rule";
41 const char DOM_SVG_SRC_TRANSFORM_ORIGIN[] = "transform-origin";
42 
43 const LinearMapNode<Color> COLOR_TABLE[] = {
44     { "aliceblue", Color(0xfff0f8ff) },
45     { "antiquewhite", Color(0xfffaebd7) },
46     { "aqua", Color(0xff00ffff) },
47     { "aquamarine", Color(0xff7fffd4) },
48     { "azure", Color(0xfff0ffff) },
49     { "beige", Color(0xfff5f5dc) },
50     { "bisque", Color(0xffffe4c4) },
51     { "black", Color(0XFF000000) },
52     { "blanchedalmond", Color(0xffffebcd) },
53     { "blue", Color(0xff0000ff) },
54     { "blueviolet", Color(0xff8a2be2) },
55     { "brown", Color(0xffa52a2a) },
56     { "burlywood", Color(0xffdeb887) },
57     { "cadetblue", Color(0xff5f9ea0) },
58     { "chartreuse", Color(0xff7fff00) },
59     { "chocolate", Color(0xffd2691e) },
60     { "coral", Color(0xffff7f50) },
61     { "cornflowerblue", Color(0xff6495ed) },
62     { "cornsilk", Color(0xfffff8dc) },
63     { "crimson", Color(0xffdc143c) },
64     { "cyan", Color(0xff00ffff) },
65     { "darkblue", Color(0xff00008b) },
66     { "darkcyan", Color(0xff008b8b) },
67     { "darkgoldenrod", Color(0xffb8860b) },
68     { "darkgray", Color(0xffa9a9a9) },
69     { "darkgreen", Color(0xff006400) },
70     { "darkgrey", Color(0xffa9a9a9) },
71     { "darkkhaki", Color(0xffbdb76b) },
72     { "darkmagenta", Color(0xff8b008b) },
73     { "darkolivegreen", Color(0xff556b2f) },
74     { "darkorange", Color(0xffff8c00) },
75     { "darkorchid", Color(0xff9932cc) },
76     { "darkred", Color(0xff8b0000) },
77     { "darksalmon", Color(0xffe9967a) },
78     { "darkseagreen", Color(0xff8fbc8f) },
79     { "darkslateblue", Color(0xff483d8b) },
80     { "darkslategray", Color(0xff2f4f4f) },
81     { "darkslategrey", Color(0xff2f4f4f) },
82     { "darkturquoise", Color(0xff00ced1) },
83     { "darkviolet", Color(0xff9400D3) },
84     { "deeppink", Color(0xffff1493) },
85     { "deepskyblue", Color(0xff00bfff) },
86     { "dimgray", Color(0xff696969) },
87     { "dimgrey", Color(0xff696969) },
88     { "dodgerblue", Color(0xff1e90ff) },
89     { "firebrick", Color(0xffb22222) },
90     { "floralwhite", Color(0xfffffaf0) },
91     { "forestgreen", Color(0xff228b22) },
92     { "fuchsia", Color(0xffff00ff) },
93     { "gainsboro", Color(0xffdcdcdc) },
94     { "ghostwhite", Color(0xfff8f8ff) },
95     { "gold", Color(0xffffd700) },
96     { "goldenrod", Color(0xffdaa520) },
97     { "gray", Color(0xff808080) },
98     { "green", Color(0xff008000) },
99     { "greenyellow", Color(0xffadff2f) },
100     { "grey", Color(0xff808080) },
101     { "honeydew", Color(0xfff0fff0) },
102     { "hotpink", Color(0xffff69b4) },
103     { "indianred", Color(0xffcd5c5c) },
104     { "indigo", Color(0xff4b0082) },
105     { "ivory", Color(0xfffffff0) },
106     { "khaki", Color(0xfff0e68c) },
107     { "lavender", Color(0xffe6e6fa) },
108     { "lavenderblush", Color(0xfffff0f5) },
109     { "lawngreen", Color(0xff7cfc00) },
110     { "lemonchiffon", Color(0xfffffacd) },
111     { "lightblue", Color(0xffadd8e6) },
112     { "lightcoral", Color(0xfff08080) },
113     { "lightcyan", Color(0xffe0ffff) },
114     { "lightgoldenrodyellow", Color(0xfffafad2) },
115     { "lightgray", Color(0xffd3d3d3) },
116     { "lightgreen", Color(0xff90ee90) },
117     { "lightgrey", Color(0xffd3d3d3) },
118     { "lightpink", Color(0xffffb6c1) },
119     { "lightsalmon", Color(0xffffa07a) },
120     { "lightseagreen", Color(0xff20b2aa) },
121     { "lightskyblue", Color(0xff87cefa) },
122     { "lightslategray", Color(0xff778899) },
123     { "lightslategrey", Color(0xff778899) },
124     { "lightsteelblue", Color(0xffb0c4de) },
125     { "lightyellow", Color(0xffffffe0) },
126     { "lime", Color(0xff00ff00) },
127     { "limegreen", Color(0xff32cd32) },
128     { "linen", Color(0xfffaf0e6) },
129     { "magenta", Color(0xffff00ff) },
130     { "maroon", Color(0xff800000) },
131     { "mediumaquamarine", Color(0xff66cdaa) },
132     { "mediumblue", Color(0xff0000cd) },
133     { "mediumorchid", Color(0xffba55d3) },
134     { "mediumpurple", Color(0xff9370db) },
135     { "mediumseagreen", Color(0xff3cb371) },
136     { "mediumslateblue", Color(0xff7b68ee) },
137     { "mediumspringgreen", Color(0xff00fa9a) },
138     { "mediumturquoise", Color(0xff48d1cc) },
139     { "mediumvioletred", Color(0xffc71585) },
140     { "midnightblue", Color(0xff191970) },
141     { "mintcream", Color(0xfff5fffa) },
142     { "mistyrose", Color(0xffffe4e1) },
143     { "moccasin", Color(0xffffe4b5) },
144     { "navajowhite", Color(0xffffdead) },
145     { "navy", Color(0xff000080) },
146     { "oldlace", Color(0xfffdf5e6) },
147     { "olive", Color(0xff808000) },
148     { "olivedrab", Color(0xff6b8e23) },
149     { "orange", Color(0xffffa500) },
150     { "orangered", Color(0xffff4500) },
151     { "orchid", Color(0xffda70d6) },
152     { "palegoldenrod", Color(0xffeee8aa) },
153     { "palegreen", Color(0xff98fb98) },
154     { "paleturquoise", Color(0xffafeeee) },
155     { "palevioletred", Color(0xffdb7093) },
156     { "papayawhip", Color(0xffffefd5) },
157     { "peachpuff", Color(0xffffdab9) },
158     { "peru", Color(0xffcd853f) },
159     { "pink", Color(0xffffc0cb) },
160     { "plum", Color(0xffdda0dd) },
161     { "powderblue", Color(0xffb0e0e6) },
162     { "purple", Color(0xff800080) },
163     { "red", Color(0xffff0000) },
164     { "rosybrown", Color(0xffbc8f8f) },
165     { "royalblue", Color(0xff4169e1) },
166     { "rebeccapurple", Color(0xff663399) },
167     { "saddlebrown", Color(0xff8b4513) },
168     { "salmon", Color(0xfffa8072) },
169     { "sandybrown", Color(0xfff4a460) },
170     { "seagreen", Color(0xff2e8b57) },
171     { "seashell", Color(0xfffff5ee) },
172     { "sienna", Color(0xffa0522d) },
173     { "silver", Color(0xffc0c0c0) },
174     { "skyblue", Color(0xff87ceeb) },
175     { "slateblue", Color(0xff6a5acd) },
176     { "slategray", Color(0xff708090) },
177     { "slategrey", Color(0xff708090) },
178     { "snow", Color(0xfffffafa) },
179     { "springgreen", Color(0xff00ff7f) },
180     { "steelblue", Color(0xff4682b4) },
181     { "tan", Color(0xffd2b48c) },
182     { "teal", Color(0xff008080) },
183     { "thistle", Color(0xffd8bfd8) },
184     { "tomato", Color(0xffff6347) },
185     { "turquoise", Color(0xff40e0d0) },
186     { "violet", Color(0xffee82ee) },
187     { "wheat", Color(0xfff5deb3) },
188     { "white", Color(0xffffffff) },
189     { "whitesmoke", Color(0xfff5f5f5) },
190     { "yellow", Color(0xffffff00) },
191     { "yellowgreen", Color(0xff9acd32) },
192 };
193 
194 } // namespace
195 
196 using namespace Framework;
197 
InitSpecialized()198 void SvgBaseDeclaration::InitSpecialized()
199 {
200     AddSpecializedAttribute(DeclarationConstants::DEFAULT_SVG_BASE_ATTR);
201 }
202 
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)203 bool SvgBaseDeclaration::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
204 {
205     return SetPresentationAttr(attr);
206 }
207 
SetSpecializedStyle(const std::pair<std::string,std::string> & style)208 bool SvgBaseDeclaration::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
209 {
210     return SetPresentationAttr(style);
211 }
212 
SetPresentationAttr(const std::pair<std::string,std::string> & attr)213 bool SvgBaseDeclaration::SetPresentationAttr(const std::pair<std::string, std::string>& attr)
214 {
215     static const LinearMapNode<void (*)(const std::string&, SvgBaseDeclaration&)> svgBaseAttrs[] = {
216         { DOM_SVG_SRC_CLIP_PATH,
217             [](const std::string& val, SvgBaseDeclaration& declaration) {
218                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
219                 auto value = StringUtils::TrimStr(val);
220                 if (value.find("url(") == 0) {
221                     auto src = std::regex_replace(value,
222                         std::regex(R"(^url\(\s*['"]?\s*#([^()]+?)\s*['"]?\s*\)$)"), "$1");
223                     attrs.clipState.SetHref(src);
224                 }
225             } },
226         { DOM_SVG_SRC_CLIP_RULE,
227             [](const std::string& val, SvgBaseDeclaration& declaration) {
228                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
229                 attrs.clipState.SetClipRule(val);
230             } },
231         { DOM_CLIP_PATH,
232             [](const std::string& val, SvgBaseDeclaration& declaration) {
233                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
234                 auto value = StringUtils::TrimStr(val);
235                 if (value.find("url(") == 0) {
236                     auto src = std::regex_replace(value,
237                         std::regex(R"(^url\(\s*['"]?\s*#([^()]+?)\s*['"]?\s*\)$)"), "$1");
238                     attrs.clipState.SetHref(src);
239                 }
240             } },
241         { DOM_SVG_CLIP_RULE,
242             [](const std::string& val, SvgBaseDeclaration& declaration) {
243                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
244                 attrs.clipState.SetClipRule(val);
245             } },
246         { DOM_SVG_FILL,
247             [](const std::string& val, SvgBaseDeclaration& declaration) {
248                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
249                 auto value = StringUtils::TrimStr(val);
250                 if (value.find("url(") == 0) {
251                     auto src = std::regex_replace(value,
252                         std::regex(R"(^url\(\s*['"]?\s*#([^()]+?)\s*['"]?\s*\)$)"), "$1");
253                     attrs.fillState.SetHref(src);
254                 } else {
255                     Color fill = (val == VALUE_NONE ? Color::TRANSPARENT : declaration.GetColor(val));
256                     attrs.fillState.SetColor(fill);
257                 }
258             } },
259         { DOM_SVG_SRC_FILL_OPACITY,
260             [](const std::string& val, SvgBaseDeclaration& declaration) {
261                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
262                 attrs.fillState.SetOpacity(std::clamp(StringToDouble(val), 0.0, 1.0));
263             } },
264         { DOM_SVG_SRC_FILL_RULE,
265             [](const std::string& val, SvgBaseDeclaration& declaration) {
266                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
267                 attrs.fillState.SetFillRule(val);
268             } },
269         { DOM_SVG_FILL_OPACITY,
270             [](const std::string& val, SvgBaseDeclaration& declaration) {
271                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
272                 attrs.fillState.SetOpacity(std::clamp(StringToDouble(val), 0.0, 1.0));
273             } },
274         { DOM_SVG_FILL_RULE,
275             [](const std::string& val, SvgBaseDeclaration& declaration) {
276                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
277                 attrs.fillState.SetFillRule(val);
278             } },
279         { DOM_SVG_FILTER,
280             [](const std::string& val, SvgBaseDeclaration& declaration) {
281                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
282                 attrs.filterId = val;
283             } },
284         { DOM_SVG_FONT_SIZE,
285             [](const std::string& val, SvgBaseDeclaration& declaration) {
286                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
287                 Dimension fontSize = StringToDimension(val);
288                 if (GreatOrEqual(fontSize.Value(), 0.0)) {
289                     attrs.textStyle.SetFontSize(fontSize);
290                 }
291             } },
292         { DOM_SVG_HREF,
293             [](const std::string& val, SvgBaseDeclaration& declaration) {
294                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
295                 auto value = StringUtils::TrimStr(val);
296                 if (value.substr(0, 1) == "#") {
297                     attrs.href = value.substr(1);
298                 }
299             } },
300         { DOM_SVG_MASK,
301             [](const std::string& val, SvgBaseDeclaration& declaration) {
302                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
303                 attrs.maskId = val;
304             } },
305         { DOM_SVG_OPACITY,
306             [](const std::string& val, SvgBaseDeclaration& declaration) {
307                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
308                 attrs.hasOpacity = true;
309                 attrs.opacity = std::clamp(StringToDouble(val), 0.0, 1.0);
310             } },
311         { DOM_SVG_STROKE,
312             [](const std::string& val, SvgBaseDeclaration& declaration) {
313                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
314                 auto value = StringUtils::TrimStr(val);
315                 if (value.find("url(") == 0) {
316                     auto src = std::regex_replace(value,
317                         std::regex(R"(^url\(\s*['"]?\s*#([^()]+?)\s*['"]?\s*\)$)"), "$1");
318                     attrs.strokeState.SetHref(src);
319                 } else {
320                     Color stroke = (val == VALUE_NONE ? Color::TRANSPARENT : declaration.GetColor(val));
321                     attrs.strokeState.SetColor(stroke);
322                 }
323             } },
324         { DOM_SVG_SRC_STROKE_DASHARRAY,
325             [](const std::string& val, SvgBaseDeclaration& declaration) {
326                 if (val.empty()) {
327                     return;
328                 }
329                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
330                 std::vector<double> lineDashVector;
331                 std::string handledStr = StringUtils::ReplaceChar(val, ',', ' ');
332                 StringUtils::StringSplitter(handledStr, ' ', lineDashVector);
333                 attrs.strokeState.SetLineDash(lineDashVector);
334             } },
335         { DOM_SVG_SRC_STROKE_DASHOFFSET,
336             [](const std::string& val, SvgBaseDeclaration& declaration) {
337                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
338                 attrs.strokeState.SetLineDashOffset(StringToDouble(val));
339             } },
340         { DOM_SVG_SRC_STROKE_LINECAP,
341             [](const std::string& val, SvgBaseDeclaration& declaration) {
342                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
343                 attrs.strokeState.SetLineCap(declaration.GetLineCapStyle(val));
344             } },
345         { DOM_SVG_SRC_STROKE_LINEJOIN,
346             [](const std::string& val, SvgBaseDeclaration& declaration) {
347                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
348                 attrs.strokeState.SetLineJoin(declaration.GetLineJoinStyle(val));
349             } },
350         { DOM_SVG_SRC_STROKE_MITERLIMIT,
351             [](const std::string& val, SvgBaseDeclaration& declaration) {
352                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
353                 double miterLimit = StringToDouble(val);
354                 if (GreatOrEqual(miterLimit, 1.0)) {
355                     attrs.strokeState.SetMiterLimit(miterLimit);
356                 }
357             } },
358         { DOM_SVG_SRC_STROKE_OPACITY,
359             [](const std::string& val, SvgBaseDeclaration& declaration) {
360                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
361                 attrs.strokeState.SetOpacity(std::clamp(StringToDouble(val), 0.0, 1.0));
362             } },
363         { DOM_SVG_SRC_STROKE_WIDTH,
364             [](const std::string& val, SvgBaseDeclaration& declaration) {
365                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
366                 Dimension lineWidth = StringToDimension(val);
367                 if (GreatOrEqual(lineWidth.Value(), 0.0)) {
368                     attrs.strokeState.SetLineWidth(lineWidth);
369                 }
370             } },
371         { DOM_SVG_STROKE_DASHARRAY,
372             [](const std::string& val, SvgBaseDeclaration& declaration) {
373                 if (val.empty()) {
374                     return;
375                 }
376                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
377                 std::vector<double> lineDashVector;
378                 StringUtils::StringSplitter(val, ' ', lineDashVector);
379                 attrs.strokeState.SetLineDash(lineDashVector);
380             } },
381         { DOM_SVG_STROKE_DASHOFFSET,
382             [](const std::string& val, SvgBaseDeclaration& declaration) {
383                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
384                 attrs.strokeState.SetLineDashOffset(StringToDouble(val));
385             } },
386         { DOM_SVG_STROKE_LINECAP,
387             [](const std::string& val, SvgBaseDeclaration& declaration) {
388                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
389                 attrs.strokeState.SetLineCap(declaration.GetLineCapStyle(val));
390             } },
391         { DOM_SVG_STROKE_LINEJOIN,
392             [](const std::string& val, SvgBaseDeclaration& declaration) {
393                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
394                 attrs.strokeState.SetLineJoin(declaration.GetLineJoinStyle(val));
395             } },
396         { DOM_SVG_STROKE_MITERLIMIT,
397             [](const std::string& val, SvgBaseDeclaration& declaration) {
398                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
399                 double miterLimit = StringToDouble(val);
400                 if (GreatOrEqual(miterLimit, 1.0)) {
401                     attrs.strokeState.SetMiterLimit(miterLimit);
402                 }
403             } },
404         { DOM_SVG_STROKE_OPACITY,
405             [](const std::string& val, SvgBaseDeclaration& declaration) {
406                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
407                 attrs.strokeState.SetOpacity(std::clamp(StringToDouble(val), 0.0, 1.0));
408             } },
409         { DOM_SVG_STROKE_WIDTH,
410             [](const std::string& val, SvgBaseDeclaration& declaration) {
411                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
412                 Dimension lineWidth = StringToDimension(val);
413                 if (GreatOrEqual(lineWidth.Value(), 0.0)) {
414                     attrs.strokeState.SetLineWidth(lineWidth);
415                 }
416             } },
417         { DOM_TRANSFORM,
418             [](const std::string& val, SvgBaseDeclaration& declaration) {
419                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
420                 attrs.transform = val;
421             } },
422         { DOM_SVG_SRC_TRANSFORM_ORIGIN,
423             [](const std::string& val, SvgBaseDeclaration& declaration) {
424                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
425                 attrs.transformOrigin = val;
426             } },
427         { DOM_SVG_XLINK_HREF,
428             [](const std::string& val, SvgBaseDeclaration& declaration) {
429                 auto& attrs = declaration.MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
430                 auto value = StringUtils::TrimStr(val);
431                 if (value.substr(0, 1) == "#") {
432                     attrs.href = value.substr(1);
433                 }
434             } }
435     };
436     auto attrIter = BinarySearchFindIndex(svgBaseAttrs, ArraySize(svgBaseAttrs), attr.first.c_str());
437     if (attrIter != -1) {
438         svgBaseAttrs[attrIter].value(attr.second, *this);
439         return true;
440     }
441     return false;
442 }
443 
444 void SvgBaseDeclaration::Inherit(const RefPtr<Declaration>& parent)
445 {
446     auto svgDeclaration = AceType::DynamicCast<SvgBaseDeclaration>(parent);
447     if (!svgDeclaration) {
448         return;
449     }
450     auto& attrs = MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
451     if (!attrs.IsValid()) {
452         LOGE("attrs is invalid");
453         return;
454     }
455     if (!attrs.hasOpacity) {
456         if (svgDeclaration->HasOpacity()) {
457             attrs.opacity = svgDeclaration->GetOpacity();
458         } else {
459             attrs.opacity = 1.0; // default opacity is 1.0
460         }
461     }
462     attrs.fillState.Inherit(svgDeclaration->GetFillState());
463     attrs.strokeState.Inherit(svgDeclaration->GetStrokeState());
464     attrs.textStyle.Inherit(svgDeclaration->GetSvgTextStyle());
465     attrs.clipState.Inherit(svgDeclaration->GetClipState());
466 }
467 
468 LineCapStyle SvgBaseDeclaration::GetLineCapStyle(const std::string& val) const
469 {
470     if (val == LINECAP_ROUND) {
471         return LineCapStyle::ROUND;
472     } else if (val == LINECAP_SQUARE) {
473         return LineCapStyle::SQUARE;
474     } else {
475         return LineCapStyle::BUTT;
476     }
477 }
478 
479 LineJoinStyle SvgBaseDeclaration::GetLineJoinStyle(const std::string& val) const
480 {
481     if (val == LINEJOIN_BEVEL) {
482         return LineJoinStyle::BEVEL;
483     } else if (val == LINEJOIN_ROUND) {
484         return LineJoinStyle::ROUND;
485     } else {
486         return LineJoinStyle::MITER;
487     }
488 }
489 
490 Color SvgBaseDeclaration::GetColor(const std::string& value) const
491 {
492     int64_t colorIndex = BinarySearchFindIndex(COLOR_TABLE, ArraySize(COLOR_TABLE), value.c_str());
493     if (colorIndex != -1) {
494         return COLOR_TABLE[colorIndex].value;
495     }
496     return Color::FromString(value);
497 }
498 
499 void SvgBaseDeclaration::ReplaceAttributes(const SvgBaseAttribute& attr)
500 {
501     auto& attribute = MaybeResetAttribute<SvgBaseAttribute>(AttributeTag::SPECIALIZED_ATTR);
502     attribute = attr;
503 }
504 } // namespace OHOS::Ace
505