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/common/font_manager.h"
17
18 #include <regex>
19
20 #include "base/i18n/localization.h"
21 #include "core/components/text/render_text.h"
22 #include "core/components_ng/base/frame_node.h"
23 #include "core/components_ng/render/font_collection.h"
24 #ifdef ENABLE_ROSEN_BACKEND
25 #ifdef TEXGINE_SUPPORT_FOR_OHOS
26 #include "texgine/src/font_config.h"
27 #include "texgine/src/font_parser.h"
28 #endif
29 #endif
30 #ifdef USE_PLATFORM_FONT
31 #include "core/common/font/font_platform_proxy.h"
32 #endif
33
34 namespace OHOS::Ace {
35
36 std::string FontManager::appCustomFont_ = "";
37 float FontManager::fontWeightScale_ = 1.0f;
38 bool FontManager::isDefaultFontChanged_ = false;
39 const std::string URL_HTTP = "http://";
40 const std::string URL_HTTPS = "https://";
41 namespace {
CheckWebUrlType(const std::string & type)42 bool CheckWebUrlType(const std::string& type)
43 {
44 return std::regex_match(type, std::regex("^http(s)?:\\/\\/.+", std::regex_constants::icase));
45 }
46
CheckHttpType(const std::string & type)47 bool CheckHttpType(const std::string& type)
48 {
49 return std::regex_match(type, std::regex("^http:\\/\\/.+", std::regex_constants::icase));
50 }
51
CheckHttpsType(const std::string & type)52 bool CheckHttpsType(const std::string& type)
53 {
54 return std::regex_match(type, std::regex("^https:\\/\\/.+", std::regex_constants::icase));
55 }
56 } // namespace
57
RegisterFont(const std::string & familyName,const std::string & familySrc,const RefPtr<PipelineBase> & context,const std::string & bundleName,const std::string & moduleName)58 void FontManager::RegisterFont(const std::string& familyName, const std::string& familySrc,
59 const RefPtr<PipelineBase>& context, const std::string& bundleName, const std::string& moduleName)
60 {
61 if (std::find(std::begin(fontNames_), std::end(fontNames_), familyName) == std::end(fontNames_)) {
62 fontNames_.emplace_back(familyName);
63 }
64
65 for (auto iter = fontLoaders_.begin(); iter != fontLoaders_.end(); ++iter) {
66 auto& fontLoader = *iter;
67 if (fontLoader->GetFamilyName() == familyName) {
68 return;
69 }
70 }
71 RefPtr<FontLoader> fontLoader = FontLoader::Create(familyName, familySrc);
72 fontLoaders_.emplace_back(fontLoader);
73 TAG_LOGI(AceLogTag::ACE_FONT,
74 "RegisterFont "
75 "[familyName:%{public}s],[familySrc:%{public}s],[bundleName:%{public}s],[moduleName:%{public}s]",
76 familyName.c_str(), familySrc.c_str(), bundleName.c_str(), moduleName.c_str());
77 fontLoader->AddFont(context, bundleName, moduleName);
78
79 fontLoader->SetVariationChanged([weak = WeakClaim(this), familyName]() {
80 auto fontManager = weak.Upgrade();
81 CHECK_NULL_VOID(fontManager);
82 fontManager->VaryFontCollectionWithFontWeightScale();
83 });
84 }
85
SetFontFamily(const char * familyName,const std::vector<std::string> & familySrc)86 void FontManager::SetFontFamily(const char* familyName, const std::vector<std::string>& familySrc)
87 {
88 RefPtr<FontLoader> fontLoader = FontLoader::CreateFontLoader(familyName, familySrc);
89 CHECK_NULL_VOID(fontLoader);
90 fontLoader->SetDefaultFontFamily(familyName, familySrc);
91 FontNodeChangeStyleNG();
92 }
93
IsDefaultFontChanged()94 bool FontManager::IsDefaultFontChanged()
95 {
96 // For AutoUI Test,render Text with High precision
97 if (SystemProperties::GetDebugAutoUIEnabled()) {
98 isDefaultFontChanged_ = true;
99 }
100 return isDefaultFontChanged_;
101 }
102
IsUseAppCustomFont() const103 bool FontManager::IsUseAppCustomFont() const
104 {
105 return !appCustomFont_.empty();
106 }
107
SetAppCustomFont(const std::string & familyName)108 void FontManager::SetAppCustomFont(const std::string& familyName)
109 {
110 appCustomFont_ = familyName;
111 }
112
GetAppCustomFont() const113 const std::string& FontManager::GetAppCustomFont() const
114 {
115 return appCustomFont_;
116 }
117
GetSystemFontList(std::vector<std::string> & fontList)118 void FontManager::GetSystemFontList(std::vector<std::string>& fontList)
119 {
120 #ifdef USE_PLATFORM_FONT
121 auto fontPlatform = FontPlatformProxy::GetInstance().GetFontPlatform();
122 if (fontPlatform) {
123 fontPlatform->GetSystemFontList(fontList);
124 }
125 #else
126 #ifdef ENABLE_ROSEN_BACKEND
127 #ifdef TEXGINE_SUPPORT_FOR_OHOS
128 Rosen::TextEngine::FontParser fontParser;
129 std::vector<Rosen::TextEngine::FontParser::FontDescriptor> systemFontList;
130 auto locale = Localization::GetInstance()->GetFontLocale();
131 systemFontList = fontParser.GetVisibilityFonts(locale);
132 for (size_t i = 0; i < systemFontList.size(); ++i) {
133 std::string fontName = systemFontList[i].fullName;
134 fontList.emplace_back(fontName);
135 }
136 #endif
137 #endif
138 #endif
139 }
140
GetUIFontConfig(FontConfigJsonInfo & info)141 void FontManager::GetUIFontConfig(FontConfigJsonInfo& info)
142 {
143 #ifdef ENABLE_ROSEN_BACKEND
144 #ifdef TEXGINE_SUPPORT_FOR_OHOS
145 Rosen::TextEngine::FontConfigJson fontConfigJson;
146 fontConfigJson.ParseFile();
147 auto rosenInfo = fontConfigJson.GetFontConfigJsonInfo();
148 // rosenInfo to FontConfigJsonInfo
149 for (size_t i = 0; i < rosenInfo->fontDirSet.size(); ++i) {
150 info.fontDirSet.emplace_back(rosenInfo->fontDirSet[i]);
151 }
152 for (size_t i = 0; i < rosenInfo->genericSet.size(); ++i) {
153 FontGenericInfo genericInfo;
154 genericInfo.familyName = rosenInfo->genericSet[i].familyName;
155 for (size_t j = 0; j < rosenInfo->genericSet[i].aliasSet.size(); ++j) {
156 AliasInfo aliasInfo;
157 aliasInfo.familyName = rosenInfo->genericSet[i].aliasSet[j].familyName;
158 aliasInfo.weight = rosenInfo->genericSet[i].aliasSet[j].weight;
159 genericInfo.aliasSet.emplace_back(aliasInfo);
160 }
161 for (size_t j = 0; j < rosenInfo->genericSet[i].adjustSet.size(); ++j) {
162 AdjustInfo adjustInfo;
163 adjustInfo.origValue = rosenInfo->genericSet[i].adjustSet[j].origValue;
164 adjustInfo.newValue = rosenInfo->genericSet[i].adjustSet[j].newValue;
165 genericInfo.adjustSet.emplace_back(adjustInfo);
166 }
167 info.genericSet.emplace_back(genericInfo);
168 }
169 for (size_t i = 0; i < rosenInfo->fallbackGroupSet.size(); ++i) {
170 FallbackGroup fallbackGroupInfo;
171 fallbackGroupInfo.groupName = rosenInfo->fallbackGroupSet[i].groupName;
172 for (size_t j = 0; j < rosenInfo->fallbackGroupSet[i].fallbackInfoSet.size(); ++j) {
173 FallbackInfo fallbackInfo;
174 fallbackInfo.familyName = rosenInfo->fallbackGroupSet[i].fallbackInfoSet[j].familyName;
175 fallbackInfo.font = rosenInfo->fallbackGroupSet[i].fallbackInfoSet[j].font;
176 fallbackGroupInfo.fallbackInfoSet.emplace_back(fallbackInfo);
177 }
178 info.fallbackGroupSet.emplace_back(fallbackGroupInfo);
179 }
180 #endif
181 #endif
182 }
183
GetSystemFont(const std::string & fontName,FontInfo & fontInfo)184 bool FontManager::GetSystemFont(const std::string& fontName, FontInfo& fontInfo)
185 {
186 bool isGetFont = false;
187 #ifdef USE_PLATFORM_FONT
188 auto fontPlatform = FontPlatformProxy::GetInstance().GetFontPlatform();
189 if (fontPlatform) {
190 isGetFont = fontPlatform->GetSystemFont(fontName, fontInfo);
191 }
192 #else
193 #ifdef ENABLE_ROSEN_BACKEND
194 #ifdef TEXGINE_SUPPORT_FOR_OHOS
195 Rosen::TextEngine::FontParser fontParser;
196 std::unique_ptr<Rosen::TextEngine::FontParser::FontDescriptor> systemFontDesc;
197 auto locale = Localization::GetInstance()->GetFontLocale();
198 systemFontDesc = fontParser.GetVisibilityFontByName(fontName, locale);
199 CHECK_NULL_RETURN(systemFontDesc, false);
200 if (fontName == systemFontDesc->fullName) {
201 fontInfo.path = systemFontDesc->path;
202 fontInfo.postScriptName = systemFontDesc->postScriptName;
203 fontInfo.fullName = systemFontDesc->fullName;
204 fontInfo.family = systemFontDesc->fontFamily;
205 fontInfo.subfamily = systemFontDesc->fontSubfamily;
206 fontInfo.weight = static_cast<uint32_t>(systemFontDesc->weight);
207 fontInfo.width = static_cast<uint32_t>(systemFontDesc->width);
208 fontInfo.italic = systemFontDesc->italic;
209 fontInfo.monoSpace = systemFontDesc->monoSpace;
210 fontInfo.symbolic = systemFontDesc->symbolic;
211 isGetFont = true;
212 }
213 #endif
214 #endif
215 #endif
216 return isGetFont;
217 }
218
RegisterCallback(const WeakPtr<RenderNode> & node,const std::string & familyName,const std::function<void ()> & callback)219 bool FontManager::RegisterCallback(
220 const WeakPtr<RenderNode>& node, const std::string& familyName, const std::function<void()>& callback)
221 {
222 CHECK_NULL_RETURN(callback, false);
223 for (auto& fontLoader : fontLoaders_) {
224 if (fontLoader->GetFamilyName() == familyName) {
225 fontLoader->SetOnLoaded(node, callback);
226 }
227 }
228 return false;
229 }
230
GetFontNames() const231 const std::vector<std::string>& FontManager::GetFontNames() const
232 {
233 return fontNames_;
234 }
235
AddFontNode(const WeakPtr<RenderNode> & node)236 void FontManager::AddFontNode(const WeakPtr<RenderNode>& node)
237 {
238 if (fontNodes_.find(node) == fontNodes_.end()) {
239 fontNodes_.emplace(node);
240 }
241 }
242
RemoveFontNode(const WeakPtr<RenderNode> & node)243 void FontManager::RemoveFontNode(const WeakPtr<RenderNode>& node)
244 {
245 fontNodes_.erase(node);
246 }
247
RebuildFontNode()248 void FontManager::RebuildFontNode()
249 {
250 #ifndef NG_BUILD
251 for (auto iter = fontNodes_.begin(); iter != fontNodes_.end();) {
252 auto fontNode = iter->Upgrade();
253 CHECK_NULL_VOID(fontNode);
254 auto renderNode = DynamicCast<RenderNode>(fontNode);
255 if (renderNode) {
256 renderNode->MarkNeedLayout();
257 ++iter;
258 } else {
259 iter = fontNodes_.erase(iter);
260 }
261 }
262 #else
263 for (auto iter = fontNodesNG_.begin(); iter != fontNodesNG_.end();) {
264 auto fontNode = iter->Upgrade();
265 CHECK_NULL_VOID(fontNode);
266 auto uiNode = DynamicCast<NG::UINode>(fontNode);
267 if (uiNode) {
268 uiNode->MarkDirtyNode(NG::PROPERTY_UPDATE_LAYOUT);
269 ++iter;
270 } else {
271 iter = fontNodesNG_.erase(iter);
272 }
273 }
274 #endif
275 }
276
UnRegisterCallback(const WeakPtr<RenderNode> & node)277 void FontManager::UnRegisterCallback(const WeakPtr<RenderNode>& node)
278 {
279 for (auto& fontLoader : fontLoaders_) {
280 fontLoader->RemoveCallback(node);
281 }
282 }
283
FontNodeChangeStyleNG()284 void FontManager::FontNodeChangeStyleNG()
285 {
286 for (auto iter = fontNodesNG_.begin(); iter != fontNodesNG_.end();) {
287 auto fontNode = iter->Upgrade();
288 CHECK_NULL_VOID(fontNode);
289 auto frameNode = DynamicCast<NG::FrameNode>(fontNode);
290 if (frameNode) {
291 frameNode->OnPropertyChangeMeasure();
292 }
293 ++iter;
294 }
295 }
296
RebuildFontNodeNG()297 void FontManager::RebuildFontNodeNG()
298 {
299 for (auto iter = fontNodesNG_.begin(); iter != fontNodesNG_.end();) {
300 auto fontNode = iter->Upgrade();
301 if (!fontNode) {
302 iter = fontNodesNG_.erase(iter);
303 continue;
304 }
305 auto uiNode = DynamicCast<NG::UINode>(fontNode);
306 if (uiNode) {
307 uiNode->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
308 auto frameNode = DynamicCast<NG::FrameNode>(fontNode);
309 if (frameNode) {
310 frameNode->OnPropertyChangeMeasure();
311 }
312 ++iter;
313 } else {
314 iter = fontNodesNG_.erase(iter);
315 }
316 }
317 for (auto iter = observers_.begin(); iter != observers_.end();) {
318 auto fontNode = iter->Upgrade();
319 if (fontNode) {
320 fontNode->OnFontChanged();
321 ++iter;
322 } else {
323 iter = observers_.erase(iter);
324 }
325 }
326 }
327
UpdateFontWeightScale()328 void FontManager::UpdateFontWeightScale()
329 {
330 float fontWeightScale = SystemProperties::GetFontWeightScale();
331 if (!NearEqual(fontWeightScale, fontWeightScale_)) {
332 fontWeightScale_ = fontWeightScale;
333 VaryFontCollectionWithFontWeightScale();
334 }
335 }
336
AddVariationNode(const WeakPtr<RenderNode> & node)337 void FontManager::AddVariationNode(const WeakPtr<RenderNode>& node)
338 {
339 if (variationNodes_.find(node) == variationNodes_.end()) {
340 variationNodes_.emplace(node);
341 }
342 }
343
RemoveVariationNode(const WeakPtr<RenderNode> & node)344 void FontManager::RemoveVariationNode(const WeakPtr<RenderNode>& node)
345 {
346 variationNodes_.erase(node);
347 }
348
NotifyVariationNodes()349 void FontManager::NotifyVariationNodes()
350 {
351 #ifndef NG_BUILD
352 for (const auto& node : variationNodes_) {
353 auto refNode = node.Upgrade();
354 CHECK_NULL_VOID(refNode);
355 auto renderNode = DynamicCast<RenderNode>(refNode);
356 CHECK_NULL_VOID(renderNode);
357 auto text = DynamicCast<RenderText>(renderNode);
358 if (text) {
359 text->MarkNeedMeasure();
360 }
361 renderNode->MarkNeedLayout();
362 }
363 #else
364 for (const auto& node : variationNodesNG_) {
365 auto uiNode = node.Upgrade();
366 CHECK_NULL_VOID(uiNode);
367 auto frameNode = DynamicCast<NG::FrameNode>(uiNode);
368 if (frameNode) {
369 frameNode->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
370 }
371 uiNode->MarkDirtyNode(NG::PROPERTY_UPDATE_LAYOUT);
372 }
373 #endif
374 }
375
RegisterCallbackNG(const WeakPtr<NG::UINode> & node,const std::string & familyName,const std::function<void ()> & callback)376 bool FontManager::RegisterCallbackNG(
377 const WeakPtr<NG::UINode>& node, const std::string& familyName, const std::function<void()>& callback)
378 {
379 CHECK_NULL_RETURN(callback, false);
380 auto hasRegistered = false;
381 for (auto& fontLoader : fontLoaders_) {
382 if (fontLoader->GetFamilyName() == familyName) {
383 fontLoader->SetOnLoadedNG(node, callback);
384 hasRegistered = true;
385 }
386 }
387 // Register callbacks for non-system fonts that are loaded through the graphic2d.
388 FontInfo fontInfo;
389 if (!hasRegistered) {
390 externalLoadCallbacks_.emplace(node, std::make_pair(familyName, callback));
391 }
392 if (!hasRegisterLoadFontCallback_) {
393 RegisterLoadFontCallbacks();
394 hasRegisterLoadFontCallback_ = true;
395 }
396 return false;
397 }
398
AddFontNodeNG(const WeakPtr<NG::UINode> & node)399 void FontManager::AddFontNodeNG(const WeakPtr<NG::UINode>& node)
400 {
401 if (fontNodesNG_.find(node) == fontNodesNG_.end()) {
402 fontNodesNG_.emplace(node);
403 }
404 }
405
RemoveFontNodeNG(const WeakPtr<NG::UINode> & node)406 void FontManager::RemoveFontNodeNG(const WeakPtr<NG::UINode>& node)
407 {
408 fontNodesNG_.erase(node);
409 }
410
UnRegisterCallbackNG(const WeakPtr<NG::UINode> & node)411 void FontManager::UnRegisterCallbackNG(const WeakPtr<NG::UINode>& node)
412 {
413 for (auto& fontLoader : fontLoaders_) {
414 fontLoader->RemoveCallbackNG(node);
415 }
416 externalLoadCallbacks_.erase(node);
417 }
418
AddVariationNodeNG(const WeakPtr<NG::UINode> & node)419 void FontManager::AddVariationNodeNG(const WeakPtr<NG::UINode>& node)
420 {
421 if (variationNodesNG_.find(node) == variationNodesNG_.end()) {
422 variationNodesNG_.emplace(node);
423 }
424 }
425
RemoveVariationNodeNG(const WeakPtr<NG::UINode> & node)426 void FontManager::RemoveVariationNodeNG(const WeakPtr<NG::UINode>& node)
427 {
428 variationNodesNG_.erase(node);
429 }
430
AddFontObserver(WeakPtr<FontChangeObserver> node)431 void FontManager::AddFontObserver(WeakPtr<FontChangeObserver> node)
432 {
433 if (observers_.find(node) == observers_.end()) {
434 observers_.emplace(node);
435 }
436 }
437
RemoveFontChangeObserver(WeakPtr<FontChangeObserver> node)438 void FontManager::RemoveFontChangeObserver(WeakPtr<FontChangeObserver> node)
439 {
440 observers_.erase(node);
441 }
442
GetFontNames()443 std::vector<std::string> FontManager::GetFontNames()
444 {
445 return fontNames_;
446 }
447
RegisterLoadFontCallbacks()448 void FontManager::RegisterLoadFontCallbacks()
449 {
450 auto context = PipelineBase::GetCurrentContextSafelyWithCheck();
451 CHECK_NULL_VOID(context);
452 NG::FontCollection::Current()->RegisterLoadFontFinishCallback(
453 [weakContext = WeakPtr(context), weak = WeakClaim(this)](const std::string& fontName) {
454 auto fontManager = weak.Upgrade();
455 CHECK_NULL_VOID(fontManager);
456 fontManager->OnLoadFontChanged(weakContext, fontName);
457 });
458 NG::FontCollection::Current()->RegisterUnloadFontFinishCallback(
459 [weakContext = WeakPtr(context), weak = WeakClaim(this)](const std::string& fontName) {
460 auto fontManager = weak.Upgrade();
461 CHECK_NULL_VOID(fontManager);
462 fontManager->OnLoadFontChanged(weakContext, fontName);
463 });
464 }
465
OnLoadFontChanged(const WeakPtr<PipelineBase> & weakContext,const std::string & fontName)466 void FontManager::OnLoadFontChanged(const WeakPtr<PipelineBase>& weakContext, const std::string& fontName)
467 {
468 auto context = weakContext.Upgrade();
469 CHECK_NULL_VOID(context);
470 auto taskExecutor = context->GetTaskExecutor();
471 CHECK_NULL_VOID(taskExecutor);
472 taskExecutor->PostTask(
473 [weak = WeakClaim(this), fontName] {
474 auto fontManager = weak.Upgrade();
475 CHECK_NULL_VOID(fontManager);
476 for (const auto& element : fontManager->externalLoadCallbacks_) {
477 if (element.second.first == fontName && element.second.second) {
478 element.second.second();
479 }
480 }
481 },
482 TaskExecutor::TaskType::UI, "NotifyFontLoadUITask");
483 }
484
StartAbilityOnJumpBrowser(const std::string & address) const485 void FontManager::StartAbilityOnJumpBrowser(const std::string& address) const
486 {
487 if (startAbilityOnJumpBrowserHandler_) {
488 startAbilityOnJumpBrowserHandler_(address);
489 }
490 }
491
StartAbilityOnInstallAppInStore(const std::string & appName) const492 void FontManager::StartAbilityOnInstallAppInStore(const std::string& appName) const
493 {
494 if (startAbilityOnInstallAppInStoreHandler_) {
495 startAbilityOnInstallAppInStoreHandler_(appName);
496 }
497 }
498
OpenLinkOnMapSearch(const std::string & address)499 void FontManager::OpenLinkOnMapSearch(const std::string& address)
500 {
501 if (startOpenLinkOnMapSearchHandler_) {
502 startOpenLinkOnMapSearchHandler_(address);
503 }
504 }
505
OnPreviewMenuOptionClick(TextDataDetectType type,const std::string & content)506 void FontManager::OnPreviewMenuOptionClick(TextDataDetectType type, const std::string& content)
507 {
508 if (type == TextDataDetectType::URL) {
509 std::string url = content;
510 if (!CheckWebUrlType(url)) {
511 url = "https://" + url;
512 } else if (CheckHttpType(url) && url.length() > URL_HTTP.length()) {
513 url.replace(0, URL_HTTP.length(), URL_HTTP);
514 } else if (CheckHttpsType(url) && url.length() > URL_HTTPS.length()) {
515 url.replace(0, URL_HTTPS.length(), URL_HTTPS);
516 }
517 StartAbilityOnJumpBrowser(url);
518 }
519
520 if (type == TextDataDetectType::ADDRESS) {
521 OpenLinkOnMapSearch(content);
522 }
523 }
524
StartAbilityOnCalendar(const std::map<std::string,std::string> & params) const525 void FontManager::StartAbilityOnCalendar(const std::map<std::string, std::string>& params) const
526 {
527 if (startAbilityOnCalendarHandler_) {
528 startAbilityOnCalendarHandler_(params);
529 }
530 }
531
AddHybridRenderNode(const WeakPtr<NG::UINode> & node)532 void FontManager::AddHybridRenderNode(const WeakPtr<NG::UINode>& node)
533 {
534 std::lock_guard<std::mutex> lock(hybridRenderNodesMutex_);
535 if (hybridRenderNodes_.find(node) == hybridRenderNodes_.end()) {
536 hybridRenderNodes_.emplace(node);
537 }
538 }
539
RemoveHybridRenderNode(const WeakPtr<NG::UINode> & node)540 void FontManager::RemoveHybridRenderNode(const WeakPtr<NG::UINode>& node)
541 {
542 std::lock_guard<std::mutex> lock(hybridRenderNodesMutex_);
543 hybridRenderNodes_.erase(node);
544 }
545
UpdateHybridRenderNodes()546 void FontManager::UpdateHybridRenderNodes()
547 {
548 std::lock_guard<std::mutex> lock(hybridRenderNodesMutex_);
549 for (auto iter = hybridRenderNodes_.begin(); iter != hybridRenderNodes_.end();) {
550 auto hybridNode = iter->Upgrade();
551 CHECK_NULL_VOID(hybridNode);
552 auto uiNode = DynamicCast<NG::UINode>(hybridNode);
553 if (uiNode != nullptr) {
554 uiNode->MarkDirtyNode(NG::PROPERTY_UPDATE_RENDER);
555 ++iter;
556 } else {
557 iter = hybridRenderNodes_.erase(iter);
558 }
559 }
560 }
561 } // namespace OHOS::Ace
562