• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.. All rights reserved.
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 "hm_symbol_run.h"
17 #include "custom_symbol_config.h"
18 #include "default_symbol_config.h"
19 #include "draw/path.h"
20 #include "hm_symbol_node_build.h"
21 #include "include/pathops/SkPathOps.h"
22 #include "utils/text_log.h"
23 #include "utils/text_trace.h"
24 
25 namespace OHOS {
26 namespace Rosen {
27 namespace SPText {
28 static const std::vector<RSEffectStrategy> COMMON_ANIMATION_TYPES = {
29     RSEffectStrategy::SCALE, RSEffectStrategy::APPEAR, RSEffectStrategy::DISAPPEAR,
30     RSEffectStrategy::BOUNCE, RSEffectStrategy::REPLACE_APPEAR, RSEffectStrategy::QUICK_REPLACE_APPEAR};
31 
32 static const float SHADOW_EPSILON = 0.999f; // if blur radius less than 1, do noe need to draw
33 
HMSymbolRun(uint64_t symbolId,const HMSymbolTxt & symbolTxt,const std::shared_ptr<RSTextBlob> & textBlob,std::function<bool (const std::shared_ptr<TextEngine::SymbolAnimationConfig> &)> & animationFunc)34 HMSymbolRun::HMSymbolRun(uint64_t symbolId,
35     const HMSymbolTxt& symbolTxt,
36     const std::shared_ptr<RSTextBlob>& textBlob,
37     std::function<bool(const std::shared_ptr<TextEngine::SymbolAnimationConfig>&)>& animationFunc)
38     : symbolTxt_(symbolTxt), symbolId_(symbolId)
39 {
40     if (textBlob) {
41         textBlob_ = textBlob;
42     } else {
43         TEXT_LOGD("Null text blob");
44     }
45     if (animationFunc) {
46         animationFunc_ = animationFunc;
47     } else {
48         TEXT_LOGD("Null animation func");
49     }
50 }
51 
GetSymbolLayers(uint16_t glyphId,const HMSymbolTxt & symbolText)52 RSSymbolLayers HMSymbolRun::GetSymbolLayers(uint16_t glyphId, const HMSymbolTxt& symbolText)
53 {
54     RSSymbolLayers symbolInfo;
55     symbolInfo.symbolGlyphId = glyphId;
56     auto& symbolInfoOrign = symbolLayersGroups_;
57     if (symbolInfoOrign.renderModeGroups.empty() || symbolInfoOrign.symbolGlyphId == 0) {
58         TEXT_LOGD("Invalid symbol layer groups, glyph id %{public}hu.", glyphId);
59         return symbolInfo;
60     }
61 
62     RSSymbolRenderingStrategy renderMode = symbolText.GetRenderMode();
63     if (symbolInfoOrign.renderModeGroups.find(renderMode) == symbolInfoOrign.renderModeGroups.end()) {
64         renderMode = RSSymbolRenderingStrategy::SINGLE;
65     }
66 
67     symbolInfo.layers = symbolInfoOrign.layers;
68     if (symbolInfoOrign.renderModeGroups.find(renderMode) != symbolInfoOrign.renderModeGroups.end()) {
69         symbolInfo.renderGroups = symbolInfoOrign.renderModeGroups[renderMode];
70         symbolInfo.symbolGlyphId = symbolInfoOrign.symbolGlyphId;
71     }
72 
73     switch (symbolText.GetSymbolColor().colorType) {
74         case SymbolColorType::GRADIENT_DEFAULT_COLOR:
75             SetGradientOrDefinedColor(symbolInfo);
76             break;
77         case SymbolColorType::GRADIENT_TYPE:
78             SetGradientColor(renderMode, symbolInfo);
79             if (gradients_.empty()) {
80                 SetRenderColor(renderMode, symbolInfo);
81             }
82             break;
83         default:
84             SetRenderColor(renderMode, symbolInfo);
85             break;
86     }
87     return symbolInfo;
88 }
89 
SetRenderColor(const RSSymbolRenderingStrategy & renderMode,RSSymbolLayers & symbolInfo)90 void HMSymbolRun::SetRenderColor(const RSSymbolRenderingStrategy& renderMode, RSSymbolLayers& symbolInfo)
91 {
92     std::vector<RSSColor> colorList = symbolTxt_.GetRenderColor();
93 
94     if (!colorList.empty()) {
95         SetSymbolRenderColor(renderMode, colorList, symbolInfo);
96     }
97 
98     std::vector<std::shared_ptr<SymbolGradient>> gradients;
99     for (const auto& group : symbolInfo.renderGroups) {
100         auto gradient = std::make_shared<SymbolGradient>();
101         std::vector<Drawing::ColorQuad> colorQuads;
102         Drawing::Color color;
103         color.SetRgb(group.color.r, group.color.g, group.color.b);
104         color.SetAlphaF(group.color.a);
105         colorQuads.push_back(color.CastToColorQuad());
106         gradient->SetColors(colorQuads);
107         gradients.push_back(gradient);
108     }
109     gradients_ = gradients;
110 }
111 
SetGradientColor(const RSSymbolRenderingStrategy & renderMode,const RSSymbolLayers & symbolInfo)112 void HMSymbolRun::SetGradientColor(const RSSymbolRenderingStrategy& renderMode, const RSSymbolLayers& symbolInfo)
113 {
114     SymbolColor symbolColor = symbolTxt_.GetSymbolColor();
115     if (symbolColor.gradients.empty()) {
116         return;
117     }
118     std::vector<std::shared_ptr<SymbolGradient>> gradients;
119     if (renderMode == RSSymbolRenderingStrategy::SINGLE) {
120         gradients.push_back(symbolColor.gradients[0]);
121         gradients_ = gradients;
122         return;
123     }
124 
125     size_t i = 0;
126     const size_t n = symbolColor.gradients.size() - 1;
127     for (size_t index = 0; index < symbolInfo.renderGroups.size(); index++) {
128         std::shared_ptr<SymbolGradient> gradient = nullptr;
129         if (i <= n) {
130             gradient = symbolColor.gradients[i];
131             i++;
132         } else {
133             gradient = SymbolNodeBuild::CreateGradient(symbolColor.gradients[n]);
134         }
135         if (gradient != nullptr) {
136             gradients.push_back(gradient);
137         }
138     }
139     gradients_ = std::move(gradients);
140 }
141 
SetGradientOrDefinedColor(const RSSymbolLayers & symbolInfo)142 void HMSymbolRun::SetGradientOrDefinedColor(const RSSymbolLayers& symbolInfo)
143 {
144     auto symbolColor = symbolTxt_.GetSymbolColor();
145     const size_t n = symbolColor.gradients.size();
146     std::vector<std::shared_ptr<SymbolGradient>> gradients;
147     for (size_t i = 0; i < symbolInfo.renderGroups.size(); i++) {
148         if (i < n && symbolColor.gradients[i]) {
149             gradients.push_back(symbolColor.gradients[i]);
150         } else {
151             auto gradient = std::make_shared<SymbolGradient>();
152             Drawing::Color color;
153             const auto& group = symbolInfo.renderGroups[i];
154             color.SetRgb(group.color.r, group.color.g, group.color.b);
155             color.SetAlphaF(group.color.a);
156             std::vector<Drawing::ColorQuad> colorQuads;
157             colorQuads.push_back(color.CastToColorQuad());
158             gradient->SetColors(colorQuads);
159             gradients.push_back(gradient);
160         }
161     }
162     gradients_ = std::move(gradients);
163 }
164 
SetSymbolRenderColor(const RSSymbolRenderingStrategy & renderMode,const std::vector<RSSColor> & colors,RSSymbolLayers & symbolInfo)165 void HMSymbolRun::SetSymbolRenderColor(const RSSymbolRenderingStrategy& renderMode,
166     const std::vector<RSSColor>& colors, RSSymbolLayers& symbolInfo)
167 {
168     if (colors.empty()) {
169         return;
170     }
171     switch (renderMode) {
172         // SINGLE and HIERARCHICAL: Supports single color setting
173         case RSSymbolRenderingStrategy::SINGLE:
174             for (size_t i = 0; i < symbolInfo.renderGroups.size(); ++i) {
175                 symbolInfo.renderGroups[i].color = colors[0]; // the 0 indicates the the first color is used
176             }
177             break;
178         // MULTIPLE_OPACITY: Supports rgb replace and alphia overlay setting by the first color
179         case RSSymbolRenderingStrategy::MULTIPLE_OPACITY:
180             for (size_t i = 0; i < symbolInfo.renderGroups.size(); ++i) {
181                 float colorAlphia = symbolInfo.renderGroups[i].color.a * colors[0].a;
182                 symbolInfo.renderGroups[i].color.a = std::clamp(colorAlphia, 0.0f, 1.0f); // 0.0: min, 1.0: max
183                 symbolInfo.renderGroups[i].color.r = colors[0].r; // the 0 indicates the the first color is used
184                 symbolInfo.renderGroups[i].color.g = colors[0].g; // the 0 indicates the the first color is used
185                 symbolInfo.renderGroups[i].color.b = colors[0].b; // the 0 indicates the the first color is used
186             }
187             break;
188         // MULTIPLE_COLOR: Supports mutiple color setting
189         case RSSymbolRenderingStrategy::MULTIPLE_COLOR:
190             for (size_t i = 0; i < symbolInfo.renderGroups.size() && i < colors.size(); ++i) {
191                 symbolInfo.renderGroups[i].color = colors[i];
192             }
193             break;
194         default:
195             break;
196     }
197 }
198 
UpdateSymbolLayersGroups(uint16_t glyphId)199 void HMSymbolRun::UpdateSymbolLayersGroups(uint16_t glyphId)
200 {
201     symbolLayersGroups_.symbolGlyphId = glyphId;
202     // Obtaining Symbol Preset LayerGroups Parameters
203     if (symbolTxt_.GetSymbolType() == SymbolType::SYSTEM) {
204         auto groups = OHOS::Rosen::Symbol::DefaultSymbolConfig::GetInstance()->GetSymbolLayersGroups(glyphId);
205         if (groups.renderModeGroups.empty()) {
206             TEXT_LOGD("Failed to get system symbol layer groups, glyph id %{public}hu", glyphId);
207             symbolLayersGroups_.renderModeGroups = {};
208             return;
209         }
210         symbolLayersGroups_ = groups;
211     } else {
212         auto groups = OHOS::Rosen::Symbol::CustomSymbolConfig::GetInstance()->GetSymbolLayersGroups(
213             symbolTxt_.familyName_, glyphId);
214         if (!groups.has_value()) {
215             TEXT_LOGD("Failed to get custom symbol layer groups, glyph id %{public}hu", glyphId);
216             symbolLayersGroups_.renderModeGroups = {};
217             return;
218         }
219         symbolLayersGroups_ = groups.value();
220     }
221 }
222 
DrawSymbol(RSCanvas * canvas,const RSPoint & offset)223 void HMSymbolRun::DrawSymbol(RSCanvas* canvas, const RSPoint& offset)
224 {
225     TEXT_TRACE_FUNC();
226     if (!textBlob_) {
227         TEXT_LOGD("Null text blob");
228         return;
229     }
230 
231     if (!canvas) {
232         TEXT_LOGD("Null canvas");
233         return;
234     }
235 
236     std::vector<uint16_t> glyphIds;
237     RSTextBlob::GetDrawingGlyphIDforTextBlob(textBlob_.get(), glyphIds);
238     if (glyphIds.size() != 1) {
239         TEXT_LOGD("Glyph isn't unique");
240         canvas->DrawTextBlob(textBlob_.get(), offset.GetX(), offset.GetY());
241         return;
242     }
243     TEXT_LOGD("HmSymbol: DrawSymbol");
244     uint16_t glyphId = glyphIds[0];
245     OHOS::Rosen::Drawing::Path path = RSTextBlob::GetDrawingPathforTextBlob(glyphId, textBlob_.get());
246     RSHMSymbolData symbolData;
247 
248     UpdateSymbolLayersGroups(glyphId);
249     symbolData.symbolInfo_ = GetSymbolLayers(glyphId, symbolTxt_);
250     if (symbolData.symbolInfo_.symbolGlyphId != glyphId) {
251         path = RSTextBlob::GetDrawingPathforTextBlob(symbolData.symbolInfo_.symbolGlyphId, textBlob_.get());
252     }
253     symbolData.path_ = path;
254     symbolData.symbolId = symbolId_; // symbolspan Id in paragraph
255     RSEffectStrategy symbolEffect = symbolTxt_.GetEffectStrategy();
256     std::pair<float, float> offsetXY(offset.GetX(), offset.GetY());
257     if (symbolEffect > 0 && symbolTxt_.GetAnimationStart()) { // 0 > has animation
258         if (SymbolAnimation(symbolData, offsetXY)) {
259             currentAnimationHasPlayed_ = true;
260             return;
261         }
262     }
263     ClearSymbolAnimation(symbolData, offsetXY);
264     OnDrawSymbol(canvas, symbolData, offset);
265     currentAnimationHasPlayed_ = false;
266 }
267 
SetRenderColor(const std::vector<RSSColor> & colorList)268 void HMSymbolRun::SetRenderColor(const std::vector<RSSColor>& colorList)
269 {
270     symbolTxt_.SetRenderColor(colorList);
271 }
272 
SetSymbolColor(const SymbolColor & symbolColor)273 void HMSymbolRun::SetSymbolColor(const SymbolColor& symbolColor)
274 {
275     symbolTxt_.SetSymbolColor(symbolColor);
276 }
277 
SetRenderMode(RSSymbolRenderingStrategy renderMode)278 void HMSymbolRun::SetRenderMode(RSSymbolRenderingStrategy renderMode)
279 {
280     symbolTxt_.SetRenderMode(renderMode);
281 }
282 
SetSymbolEffect(const RSEffectStrategy & effectStrategy)283 void HMSymbolRun::SetSymbolEffect(const RSEffectStrategy& effectStrategy)
284 {
285     symbolTxt_.SetSymbolEffect(effectStrategy);
286     currentAnimationHasPlayed_ = false;
287 }
288 
SetAnimationMode(uint16_t animationMode)289 void HMSymbolRun::SetAnimationMode(uint16_t animationMode)
290 {
291     symbolTxt_.SetAnimationMode(animationMode);
292     currentAnimationHasPlayed_ = false;
293 }
294 
SetAnimationStart(bool animationStart)295 void HMSymbolRun::SetAnimationStart(bool animationStart)
296 {
297     symbolTxt_.SetAnimationStart(animationStart);
298     currentAnimationHasPlayed_ = false;
299 }
300 
SetCommonSubType(Drawing::DrawingCommonSubType commonSubType)301 void HMSymbolRun::SetCommonSubType(Drawing::DrawingCommonSubType commonSubType)
302 {
303     symbolTxt_.SetCommonSubType(commonSubType);
304     currentAnimationHasPlayed_ = false;
305 }
306 
GetSymbolUid() const307 uint64_t HMSymbolRun::GetSymbolUid() const
308 {
309     return symbolTxt_.GetSymbolUid();
310 }
311 
SetSymbolUid(uint64_t symbolUid)312 void HMSymbolRun::SetSymbolUid(uint64_t symbolUid)
313 {
314     symbolTxt_.SetSymbolUid(symbolUid);
315     symbolId_ = symbolUid;
316 }
317 
SetSymbolTxt(const HMSymbolTxt & hmsymbolTxt)318 void HMSymbolRun::SetSymbolTxt(const HMSymbolTxt& hmsymbolTxt)
319 {
320     symbolTxt_ = hmsymbolTxt;
321 }
322 
GetSymbolTxt()323 const HMSymbolTxt& HMSymbolRun::GetSymbolTxt()
324 {
325     return symbolTxt_;
326 }
327 
SetSymbolShadow(const std::optional<SymbolShadow> & symbolShadow)328 void HMSymbolRun::SetSymbolShadow(const std::optional<SymbolShadow>& symbolShadow)
329 {
330     if (symbolTxt_.GetSymbolShadow().has_value() != symbolShadow.has_value()) {
331         currentAnimationHasPlayed_ = false;
332     }
333     symbolTxt_.SetSymbolShadow(symbolShadow);
334 }
335 
SetAnimation(const std::function<bool (const std::shared_ptr<OHOS::Rosen::TextEngine::SymbolAnimationConfig> &)> & animationFunc)336 void HMSymbolRun::SetAnimation(
337     const std::function<bool(const std::shared_ptr<OHOS::Rosen::TextEngine::SymbolAnimationConfig>&)>&
338     animationFunc)
339 {
340     if (animationFunc) {
341         animationFunc_ = animationFunc;
342     }
343 }
344 
SetTextBlob(const std::shared_ptr<RSTextBlob> & textBlob)345 void HMSymbolRun::SetTextBlob(const std::shared_ptr<RSTextBlob>& textBlob)
346 {
347     if (textBlob) {
348         std::vector<uint16_t> glyphId1;
349         std::vector<uint16_t> glyphId2;
350         RSTextBlob::GetDrawingGlyphIDforTextBlob(textBlob_.get(), glyphId1);
351         RSTextBlob::GetDrawingGlyphIDforTextBlob(textBlob.get(), glyphId2);
352         // 1 mean the textBlob has one symbol
353         if (!(glyphId1.size() == 1 && glyphId2.size() == 1 && glyphId1[0] == glyphId2[0])) {
354             currentAnimationHasPlayed_ = false;
355         }
356         textBlob_ = textBlob;
357     }
358 }
359 
DrawPaths(RSCanvas * canvas,const std::vector<RSPath> & multPaths,const RSPath & path)360 void HMSymbolRun::DrawPaths(RSCanvas* canvas, const std::vector<RSPath>& multPaths,
361     const RSPath& path)
362 {
363     Drawing::Brush brush;
364     Drawing::Pen pen;
365     brush.SetAntiAlias(true);
366     pen.SetAntiAlias(true);
367 
368     size_t n = gradients_.size();
369     bool isSingle = symbolTxt_.GetRenderMode() == RSSymbolRenderingStrategy::SINGLE && n > 0 &&
370         gradients_[0] != nullptr;
371     if (isSingle) { // if renderMode is SINGLE only set one color
372         gradients_[0]->Make(path.GetBounds());
373         brush = gradients_[0]->CreateGradientBrush();
374         pen = gradients_[0]->CreateGradientPen();
375     }
376 
377     size_t i = 0;
378     for (const auto& multPath: multPaths) {
379         bool isValid = symbolTxt_.GetRenderMode() != RSSymbolRenderingStrategy::SINGLE && i < n &&
380             gradients_[i] != nullptr;
381         if (isValid) {
382             gradients_[i]->Make(multPath.GetBounds());
383             brush = gradients_[i]->CreateGradientBrush();
384             pen = gradients_[i]->CreateGradientPen();
385             i = i + 1 < n ? i + 1 : i;
386         }
387         canvas->AttachPen(pen);
388         canvas->AttachBrush(brush);
389         canvas->DrawPath(multPath);
390         canvas->DetachBrush();
391         canvas->DetachPen();
392     }
393 }
394 
OnDrawSymbol(RSCanvas * canvas,const RSHMSymbolData & symbolData,RSPoint locate)395 void HMSymbolRun::OnDrawSymbol(RSCanvas* canvas, const RSHMSymbolData& symbolData, RSPoint locate)
396 {
397     TEXT_TRACE_FUNC();
398     RSPath path(symbolData.path_);
399 
400     // 1.0 move path
401     path.Offset(locate.GetX(), locate.GetY());
402     if (symbolData.symbolInfo_.renderGroups.empty()) {
403         TEXT_LOGD("Empty render groups");
404         canvas->DrawPath(path);
405         return;
406     }
407 
408     // 2.0 split path
409     std::vector<RSPath> paths;
410     RSHMSymbol::PathOutlineDecompose(path, paths);
411     std::vector<RSPath> pathLayers;
412     RSHMSymbol::MultilayerPath(symbolData.symbolInfo_.layers, paths, pathLayers);
413     // Stratification
414     std::vector<RSRenderGroup> groups = symbolData.symbolInfo_.renderGroups;
415     TEXT_LOGD("RenderGroup size %{public}zu", groups.size());
416     std::vector<RSPath> multPaths;
417     for (auto group : groups) {
418         RSPath multPath;
419         SymbolNodeBuild::MergeDrawingPath(multPath, group, pathLayers);
420         multPaths.push_back(multPath);
421     }
422 
423     if (symbolTxt_.GetSymbolShadow().has_value() &&
424         symbolTxt_.GetSymbolShadow().value().blurRadius > SHADOW_EPSILON) {
425         DrawSymbolShadow(canvas, multPaths);
426     }
427 
428     DrawPaths(canvas, multPaths, path);
429 }
430 
DrawSymbolShadow(RSCanvas * canvas,const std::vector<RSPath> & multPaths)431 void HMSymbolRun::DrawSymbolShadow(RSCanvas* canvas, const std::vector<RSPath>& multPaths)
432 {
433     auto shadow = symbolTxt_.GetSymbolShadow().value();
434     Drawing::Filter filter;
435     filter.SetMaskFilter(Drawing::MaskFilter::CreateBlurMaskFilter(Drawing::BlurType::NORMAL,
436         shadow.blurRadius, false));
437     Drawing::Brush brush;
438     brush.SetAntiAlias(true);
439     brush.SetFilter(filter);
440 
441     RSRecordingCanvas* recordingCanvas = nullptr;
442     if (canvas->GetDrawingType() == Drawing::DrawingType::RECORDING) {
443         recordingCanvas = static_cast<RSRecordingCanvas*>(canvas);
444     }
445     if (recordingCanvas != nullptr) {
446         recordingCanvas->GetDrawCmdList()->SetHybridRenderType(RSHybridRenderType::NONE);
447     }
448 
449     RSColor color;
450     for (size_t i = 0; i < multPaths.size(); i++) {
451         RSPath multPath = multPaths[i];
452         multPath.Offset(shadow.offset.GetX(), shadow.offset.GetY());
453         color = shadow.color;
454         bool isNeedSet = i < gradients_.size() && gradients_[i] && !gradients_[i]->GetColors().empty();
455         if (isNeedSet) {
456             auto colorQuad = gradients_[i]->GetColors()[0];
457             RSColor color1(colorQuad);
458             color.SetAlphaF(shadow.color.GetAlphaF() * color1.GetAlphaF());
459         }
460         brush.SetColor(color);
461         canvas->AttachBrush(brush);
462         canvas->DrawPath(multPath);
463         canvas->DetachBrush();
464     }
465 }
466 
SymbolAnimation(const RSHMSymbolData & symbol,const std::pair<float,float> & offset)467 bool HMSymbolRun::SymbolAnimation(const RSHMSymbolData& symbol, const std::pair<float, float>& offset)
468 {
469     TEXT_TRACE_FUNC();
470     RSEffectStrategy effectMode = symbolTxt_.GetEffectStrategy();
471     uint16_t animationMode = symbolTxt_.GetAnimationMode();
472     if (effectMode == RSEffectStrategy::NONE) {
473         TEXT_LOGD("Invalid effect mode");
474         return false;
475     }
476     RSAnimationSetting animationSetting;
477     if (animationMode == 0 || effectMode == RSEffectStrategy::VARIABLE_COLOR) {
478         if (!GetAnimationGroups(effectMode, animationSetting)) {
479             TEXT_LOGD("Invalid animation setting");
480             return false;
481         }
482 
483         if (std::find(COMMON_ANIMATION_TYPES.begin(), COMMON_ANIMATION_TYPES.end(), effectMode) !=
484             COMMON_ANIMATION_TYPES.end() && animationSetting.groupSettings.size() == 1) {
485             animationMode = 1; // the 1 is wholeSymbol effect
486         }
487     }
488     SymbolNodeBuild symbolNode = SymbolNodeBuild(animationSetting, symbol, effectMode, offset);
489     symbolNode.SetAnimation(animationFunc_);
490     symbolNode.SetSymbolId(symbolId_);
491     symbolNode.SetAnimationMode(animationMode);
492     symbolNode.SetRepeatCount(symbolTxt_.GetRepeatCount());
493     symbolNode.SetAnimationStart(symbolTxt_.GetAnimationStart());
494     symbolNode.SetCommonSubType(symbolTxt_.GetCommonSubType());
495     symbolNode.SetCurrentAnimationHasPlayed(currentAnimationHasPlayed_);
496     symbolNode.SetRenderMode(symbolTxt_.GetRenderMode());
497     symbolNode.SetGradients(gradients_);
498     symbolNode.SetSymbolShadow(symbolTxt_.GetSymbolShadow());
499     symbolNode.SetSlope(animationSetting.slope);
500     if (effectMode == RSEffectStrategy::DISABLE) {
501         symbolNode.SetCommonSubType(animationSetting.commonSubType);
502     }
503     bool isNeed = (symbolTxt_.GetRenderMode() != RSSymbolRenderingStrategy::SINGLE &&
504         gradients_.size() < symbolTxt_.GetGradients().size());
505     if (isNeed) {
506         auto gradients = symbolTxt_.GetGradients();
507         symbolNode.SetDisableSlashColor(gradients[gradients_.size()]);
508     }
509     return symbolNode.DecomposeSymbolAndDraw();
510 }
511 
ClearSymbolAnimation(const RSHMSymbolData & symbol,const std::pair<float,float> & offset)512 void HMSymbolRun::ClearSymbolAnimation(const RSHMSymbolData& symbol, const std::pair<float, float>& offset)
513 {
514     auto effectMode = RSEffectStrategy::NONE;
515     RSAnimationSetting animationSetting;
516 
517     SymbolNodeBuild symbolNode = SymbolNodeBuild(animationSetting, symbol, effectMode, offset);
518     symbolNode.SetAnimation(animationFunc_);
519     symbolNode.SetSymbolId(symbolId_);
520     symbolNode.ClearAnimation();
521 }
522 
GetAnimationGroups(const RSEffectStrategy effectStrategy,RSAnimationSetting & animationOut)523 bool HMSymbolRun::GetAnimationGroups(const RSEffectStrategy effectStrategy,
524     RSAnimationSetting& animationOut)
525 {
526     RSAnimationType animationType = static_cast<RSAnimationType>(effectStrategy);
527 
528     for (const auto& animationSetting : symbolLayersGroups_.animationSettings) {
529         if (std::find(animationSetting.animationTypes.begin(), animationSetting.animationTypes.end(),
530             animationType) == animationSetting.animationTypes.end()) {
531             continue;
532         }
533         if (!animationSetting.groupSettings.empty()) {
534             animationOut = animationSetting;
535             return true;
536         }
537     }
538     return false;
539 }
540 }
541 }
542 }