1 /*
2 * Copyright (c) 2022 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_ng/svg/svg_context.h"
17
18 #include <sys/time.h>
19 #include "core/components_ng/svg/base/svg_length_scale_rule.h"
20 #include "core/components_ng/svg/parse/svg_node.h"
21
22 namespace OHOS::Ace::NG {
23 namespace {
24 #ifdef __OHOS__
25 constexpr int32_t MILLISECOND_DIVIDER = 1000;
26 constexpr int32_t TIME_LENGTH = 50;
27 #endif
28 }
GetSvgNodeById(const std::string & id) const29 RefPtr<SvgNode> SvgContext::GetSvgNodeById(const std::string& id) const
30 {
31 auto item = idMapper_.find(id);
32 if (item != idMapper_.end()) {
33 return item->second.Upgrade();
34 }
35 return nullptr;
36 }
37
PushStyle(const std::string & styleName,const std::pair<std::string,std::string> & attrPair)38 void SvgContext::PushStyle(const std::string& styleName, const std::pair<std::string, std::string>& attrPair)
39 {
40 const auto& arrMapIter = styleMap_.find(styleName);
41 if (arrMapIter == styleMap_.end()) {
42 AttrMap attrMap;
43 attrMap.emplace(attrPair);
44 styleMap_.emplace(std::make_pair(styleName, attrMap));
45 } else {
46 if (arrMapIter->second.find(attrPair.first) != arrMapIter->second.end()) {
47 arrMapIter->second.erase(attrPair.first);
48 }
49 arrMapIter->second.emplace(attrPair);
50 }
51 }
52
GetAttrMap(const std::string & key) const53 const AttrMap& SvgContext::GetAttrMap(const std::string& key) const
54 {
55 auto styleClassIter = styleMap_.find(key);
56 if (styleClassIter != styleMap_.end()) {
57 return styleClassIter->second;
58 }
59 static AttrMap emptyMap;
60 return emptyMap;
61 }
62
AddAnimator(int32_t key,const RefPtr<Animator> & animator)63 void SvgContext::AddAnimator(int32_t key, const RefPtr<Animator>& animator)
64 {
65 animators_[key] = animator;
66 }
67
RemoveAnimator(int32_t key)68 void SvgContext::RemoveAnimator(int32_t key)
69 {
70 animators_.erase(key);
71 }
72
ControlAnimators(bool play)73 void SvgContext::ControlAnimators(bool play)
74 {
75 for (auto it = animators_.begin(); it != animators_.end();) {
76 auto animator = it->second.Upgrade();
77 if (!animator) {
78 LOGW("null animator in map");
79 it = animators_.erase(it);
80 continue;
81 }
82 if (play) {
83 animator->Play();
84 } else {
85 animator->Pause();
86 }
87 ++it;
88 }
89 }
90
SetOnAnimationFinished(const std::function<void ()> & onFinishCallback)91 void SvgContext::SetOnAnimationFinished(const std::function<void()>& onFinishCallback)
92 {
93 onFinishCallbacks_.emplace_back(std::move(onFinishCallback));
94 }
95
OnAnimationFinished()96 void SvgContext::OnAnimationFinished()
97 {
98 bool allDone = true;
99 for (auto it = animators_.begin(); it != animators_.end();) {
100 auto animator = it->second.Upgrade();
101 if (!animator) {
102 TAG_LOGW(AceLogTag::ACE_IMAGE, "null animator in map");
103 continue;
104 }
105 ++it;
106 if (!animator->IsStopped()) {
107 allDone = false;
108 break;
109 }
110 }
111 if (allDone) {
112 for (const auto& callback : onFinishCallbacks_) {
113 callback();
114 }
115 }
116 }
117
SetFuncAnimateFlush(FuncAnimateFlush && funcAnimateFlush,const WeakPtr<CanvasImage> & imagePtr)118 void SvgContext::SetFuncAnimateFlush(FuncAnimateFlush&& funcAnimateFlush, const WeakPtr<CanvasImage>& imagePtr)
119 {
120 CHECK_NULL_VOID(funcAnimateFlush);
121 animateCallbacks_[imagePtr] = funcAnimateFlush;
122 }
123
AnimateFlush()124 void SvgContext::AnimateFlush()
125 {
126 CHECK_RUN_ON(UI);
127 CHECK_NULL_VOID(!animateCallbacks_.empty());
128 for (auto it = animateCallbacks_.begin(); it != animateCallbacks_.end();) {
129 if (it->first.Upgrade()) {
130 it->second();
131 ++it;
132 } else {
133 it = animateCallbacks_.erase(it);
134 }
135 }
136 }
137
GetBoundingRect(RefPtr<SvgNode> & boxNode,const SvgLengthScaleRule & boxMeasureRule)138 Rect GetBoundingRect(RefPtr<SvgNode>& boxNode, const SvgLengthScaleRule& boxMeasureRule)
139 {
140 CHECK_NULL_RETURN(boxNode, Rect());
141 auto boxRect = boxNode->AsPath(boxMeasureRule).GetBounds();
142 return Rect(boxRect.GetLeft(), boxRect.GetTop(), boxRect.GetWidth(), boxRect.GetHeight());
143 }
144
SetFuncNormalizeToPx(const FuncNormalizeToPx & funcNormalizeToPx)145 void SvgContext::SetFuncNormalizeToPx(const FuncNormalizeToPx& funcNormalizeToPx)
146 {
147 funcNormalizeToPx_ = funcNormalizeToPx;
148 }
149
CreateDumpInfo(SvgDumpInfo dumpInfo)150 void SvgContext::CreateDumpInfo(SvgDumpInfo dumpInfo)
151 {
152 dumpInfo_ = dumpInfo;
153 }
154
SetSvgDrawPathInfoDump(const std::string & pathInfo)155 void SvgContext::SetSvgDrawPathInfoDump(const std::string& pathInfo)
156 {
157 dumpInfo_.SetSvgDrawPathInfoDump(std::move(pathInfo));
158 hasRecordedPath_ = true;
159 }
160
GetDumpInfo()161 std::string SvgContext::GetDumpInfo()
162 {
163 return dumpInfo_.ToString();
164 }
165
NormalizeToPx(const Dimension & value)166 double SvgContext::NormalizeToPx(const Dimension& value)
167 {
168 if (funcNormalizeToPx_ == nullptr) {
169 return 0.0;
170 }
171 return funcNormalizeToPx_(value);
172 }
173
GetCurrentTimeString()174 std::string SvgContext::GetCurrentTimeString()
175 {
176 #ifdef __OHOS__
177 struct timeval tv;
178 gettimeofday(&tv, NULL);
179 struct tm ptm;
180 localtime_noenv_r(&tv.tv_sec, &ptm);
181 char timeStr[TIME_LENGTH] = { 0 };
182 size_t charsWritten = strftime(timeStr, TIME_LENGTH, "%Y-%m-%d %H:%M:%S:", &ptm);
183 if (charsWritten > 0) {
184 return std::string(timeStr).append(std::to_string(tv.tv_usec / MILLISECOND_DIVIDER));
185 }
186 #endif
187 return "";
188 }
189 } // namespace OHOS::Ace::NG
190