From 770340302f2ff0aa05584da5e692ee9e0ea1c25b Mon Sep 17 00:00:00 2001 From: mazijian Date: Mon, 23 Jun 2025 15:34:01 +0800 Subject: [PATCH] =?UTF-8?q?drawModifier=E9=87=8D=E7=BD=AE=E4=B8=8E?= =?UTF-8?q?=E9=87=8D=E7=BB=98=E8=A1=8C=E4=B8=BA=E5=8F=98=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: mazijian --- .../jsview/js_view_abstract.cpp | 15 +- .../components_ng/base/extension_handler.h | 3 + .../core/components_ng/base/frame_node.cpp | 10 +- .../core/base/frame_node_test_ng_coverage.cpp | 479 ++++++++++++++++++ 4 files changed, 504 insertions(+), 3 deletions(-) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp index 8bdd1606897..5b7563c947b 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp @@ -9742,7 +9742,7 @@ void AddInvalidateFunc(JSRef jsDrawModifier, NG::FrameNode* frameNode) void JSViewAbstract::JsDrawModifier(const JSCallbackInfo& info) { - if (!info[0]->IsObject()) { + if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWENTY) && !info[0]->IsObject()) { return; } @@ -9751,6 +9751,19 @@ void JSViewAbstract::JsDrawModifier(const JSCallbackInfo& info) if (!IsSupportDrawModifier) { return; } + if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWENTY) && !info[0]->IsObject()) { + ViewAbstractModel::GetInstance()->SetDrawModifier(nullptr); + if (frameNode) { + const auto& extensionHandler = frameNode->GetExtensionHandler(); + if (extensionHandler) { + extensionHandler->InvalidateRender(); + extensionHandler->ForegroundRender(); + } else { + frameNode->MarkDirtyNode(NG::PROPERTY_UPDATE_RENDER); + } + } + return; + } auto jsDrawModifier = JSRef::Cast(info[0]); RefPtr drawModifier = AceType::MakeRefPtr(); auto execCtx = info.GetExecutionContext(); diff --git a/frameworks/core/components_ng/base/extension_handler.h b/frameworks/core/components_ng/base/extension_handler.h index b251508fe6c..f5cd8ca21b2 100644 --- a/frameworks/core/components_ng/base/extension_handler.h +++ b/frameworks/core/components_ng/base/extension_handler.h @@ -120,6 +120,9 @@ public: virtual bool NeedRender() const { + if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWENTY)) { + return needRender_ ; + } return drawModifier_ || needRender_ ; } diff --git a/frameworks/core/components_ng/base/frame_node.cpp b/frameworks/core/components_ng/base/frame_node.cpp index b3be2fcf07b..9105d2985d8 100755 --- a/frameworks/core/components_ng/base/frame_node.cpp +++ b/frameworks/core/components_ng/base/frame_node.cpp @@ -4995,8 +4995,14 @@ bool FrameNode::OnLayoutFinish(bool& needSyncRsNode, DirtySwapConfig& config) auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config); needRerender = needRerender || pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config.skipMeasure, config.skipLayout); - if (needRerender || (extensionHandler_ && extensionHandler_->NeedRender()) || - CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) { + if (GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWENTY)) { + auto skippedMeasure = config.skipMeasure || SkipMeasureContent(); + needRerender = needRerender || (extensionHandler_ && + (extensionHandler_->NeedRender() || (extensionHandler_->HasDrawModifier() && !skippedMeasure))); + } else { + needRerender = needRerender || (extensionHandler_ && extensionHandler_->NeedRender()); + } + if (needRerender || CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) { MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER); } layoutAlgorithm_.Reset(); diff --git a/test/unittest/core/base/frame_node_test_ng_coverage.cpp b/test/unittest/core/base/frame_node_test_ng_coverage.cpp index 97f146a9bb5..5ca52b31fd0 100755 --- a/test/unittest/core/base/frame_node_test_ng_coverage.cpp +++ b/test/unittest/core/base/frame_node_test_ng_coverage.cpp @@ -2843,4 +2843,483 @@ HWTEST_F(FrameNodeTestNg, OnLayoutFinish002, TestSize.Level1) EXPECT_EQ(frameNode->renderContext_->GetOuterBorderRadius()->radiusTopRight.value().Value(), 20.0f); EXPECT_FALSE(result); } + + +/** + * @tc.name: OnLayoutFinish003 + * @tc.desc: Test frameNode OnLayoutFinish + * @tc.type: FUNC + */ +HWTEST_F(FrameNodeTestNg, OnLayoutFinish003, TestSize.Level1) +{ + /** + * @tc.steps: step1. create frameNode. + */ + auto frameNode = FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, 1, AceType::MakeRefPtr(), true); + EXPECT_NE(frameNode->pattern_, nullptr); + + /** + * @tc.steps: step2. isLayoutNode_ true and context true, test OnLayoutFinish. + * @tc.expected: result return false. + */ + bool needSyncRsNode = true; + DirtySwapConfig config; + frameNode->isLayoutNode_ = true; + auto context = AceType::MakeRefPtr(); + frameNode->context_ = AceType::RawPtr(context); + auto result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_FALSE(result); + + /** + * @tc.steps: step3. isLayoutNode_ true and context false, test OnLayoutFinish. + * @tc.expected: result return false. + */ + frameNode->context_ = nullptr; + result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_FALSE(result); + + /** + * @tc.steps: step4. isLayoutNode_ false, test OnLayoutFinish. + * @tc.expected: result return false. + */ + frameNode->isLayoutNode_ = false; + result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_FALSE(result); +} + +/** + * @tc.name: OnLayoutFinish004 + * @tc.desc: Test frameNode OnLayoutFinish + * @tc.type: FUNC + */ +HWTEST_F(FrameNodeTestNg, OnLayoutFinish004, TestSize.Level1) +{ + /** + * @tc.steps: step1. create frameNode. + */ + auto frameNode = FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, 1, AceType::MakeRefPtr(), true); + EXPECT_NE(frameNode->pattern_, nullptr); + + /** + * @tc.steps: step2. isActive_ false and hasTransition false, test OnLayoutFinish. + * @tc.expected: result return false. + */ + bool needSyncRsNode = true; + DirtySwapConfig config; + frameNode->isActive_ = false; + auto layoutProperty = AceType::MakeRefPtr(); + layoutProperty->geometryTransition_ = nullptr; + frameNode->layoutProperty_ = layoutProperty; + auto result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_FALSE(result); + + /** + * @tc.steps: step3. isActive_ false and hasTransition true, test OnLayoutFinish. + * @tc.expected: result return false. + */ + auto geometryTransition = AceType::MakeRefPtr("active"); + layoutProperty->geometryTransition_ = geometryTransition; + frameNode->layoutProperty_ = layoutProperty; + result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_FALSE(result); + + /** + * @tc.steps: step4. isActive_ true, test OnLayoutFinish. + * @tc.expected: result return false. + */ + frameNode->isActive_ = true; + result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_FALSE(result); +} + +/** + * @tc.name: OnLayoutFinish005 + * @tc.desc: Test frameNode OnLayoutFinish + * @tc.type: FUNC + */ +HWTEST_F(FrameNodeTestNg, OnLayoutFinish005, TestSize.Level1) +{ + /** + * @tc.steps: step1. create frameNode. + */ + auto frameNode = FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, 1, AceType::MakeRefPtr(), true); + EXPECT_NE(frameNode->pattern_, nullptr); + + /** + * @tc.steps: step2. needSkipSyncGeometryNode_ true and geometryTransition null, test OnLayoutFinish. + * @tc.expected: result return false. + */ + bool needSyncRsNode = true; + DirtySwapConfig config; + frameNode->isActive_ = true; + frameNode->needSkipSyncGeometryNode_ = true; + auto layoutProperty = AceType::MakeRefPtr(); + layoutProperty->geometryTransition_ = nullptr; + frameNode->layoutProperty_ = layoutProperty; + auto result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_FALSE(result); + + /** + * @tc.steps: step3. needSkipSyncGeometryNode_ true and geometryTransition valid,, test OnLayoutFinish. + * @tc.expected: result return false. + */ + auto geometryTransition = AceType::MakeRefPtr("active"); + layoutProperty->geometryTransition_ = geometryTransition; + frameNode->layoutProperty_ = layoutProperty; + result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_FALSE(result); + + /** + * @tc.steps: step4. needSkipSyncGeometryNode_ false, test OnLayoutFinish. + * @tc.expected: result return false. + */ + frameNode->needSkipSyncGeometryNode_ = false; + result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_FALSE(result); +} + +/** + * @tc.name: OnLayoutFinish006 + * @tc.desc: Test frameNode OnLayoutFinish + * @tc.type: FUNC + */ +HWTEST_F(FrameNodeTestNg, OnLayoutFinish006, TestSize.Level1) +{ + /** + * @tc.steps: step1. create frameNode. + */ + auto frameNode = FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, 1, AceType::MakeRefPtr(), true); + EXPECT_NE(frameNode->pattern_, nullptr); + + /** + * @tc.steps: step2. oldGeometryNode_ valid, test OnLayoutFinish. + * @tc.expected: result return false. + */ + bool needSyncRsNode = true; + DirtySwapConfig config; + frameNode->isActive_ = true; + frameNode->needSkipSyncGeometryNode_ = false; + frameNode->oldGeometryNode_ = AceType::MakeRefPtr(); + auto result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_FALSE(result); + + /** + * @tc.steps: step3. oldGeometryNode_ null, test OnLayoutFinish. + * @tc.expected: result return false. + */ + frameNode->oldGeometryNode_ = nullptr; + result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_FALSE(result); +} + +/** + * @tc.name: OnLayoutFinish007 + * @tc.desc: Test frameNode OnLayoutFinish + * @tc.type: FUNC + */ +HWTEST_F(FrameNodeTestNg, OnLayoutFinish007, TestSize.Level1) +{ + /** + * @tc.steps: step1. create frameNode. + */ + auto frameNode = FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, 1, AceType::MakeRefPtr(), true); + EXPECT_NE(frameNode->pattern_, nullptr); + + /** + * @tc.steps: step2. tag equals V2::PAGE_ETS_TAG, test OnLayoutFinish. + * @tc.expected: result return false. + */ + bool needSyncRsNode = true; + DirtySwapConfig config; + frameNode->isActive_ = true; + frameNode->needSkipSyncGeometryNode_ = false; + auto result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_FALSE(result); + + /** + * @tc.steps: step3. tag not equals V2::PAGE_ETS_TAG, test OnLayoutFinish. + * @tc.expected: result return false. + */ + frameNode->tag_ = "frameNode"; + result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_FALSE(result); +} + +/** + * @tc.name: OnLayoutFinish008 + * @tc.desc: Test frameNode OnLayoutFinish + * @tc.type: FUNC + */ +HWTEST_F(FrameNodeTestNg, OnLayoutFinish008, TestSize.Level1) +{ + /** + * @tc.steps: step1. create frameNode. + */ + auto frameNode = FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, 1, AceType::MakeRefPtr(), true); + EXPECT_NE(frameNode->pattern_, nullptr); + + /** + * @tc.steps: step2. config.skipMeasure false and config.skipLayout false, test OnLayoutFinish. + * @tc.expected: result return true. + */ + bool needSyncRsNode = true; + DirtySwapConfig config; + frameNode->isActive_ = true; + frameNode->needSkipSyncGeometryNode_ = false; + auto layoutAlgorithmWrapper = AceType::MakeRefPtr(nullptr); + frameNode->layoutAlgorithm_ = layoutAlgorithmWrapper; + layoutAlgorithmWrapper->skipMeasure_ = false; + layoutAlgorithmWrapper->skipLayout_ = false; + auto result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_TRUE(result); + + /** + * @tc.steps: step3. config.skipMeasure false and config.skipLayout true, test OnLayoutFinish. + * @tc.expected: result return true. + */ + layoutAlgorithmWrapper = AceType::MakeRefPtr(nullptr); + frameNode->layoutAlgorithm_ = layoutAlgorithmWrapper; + layoutAlgorithmWrapper->skipMeasure_ = false; + layoutAlgorithmWrapper->skipLayout_ = true; + result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_TRUE(result); + + /** + * @tc.steps: step4. config.skipMeasure true, test OnLayoutFinish. + * @tc.expected: result return true. + */ + layoutAlgorithmWrapper = AceType::MakeRefPtr(nullptr); + frameNode->layoutAlgorithm_ = layoutAlgorithmWrapper; + layoutAlgorithmWrapper->skipMeasure_ = true; + layoutAlgorithmWrapper->skipLayout_ = true; + result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_TRUE(result); +} + +/** + * @tc.name: OnLayoutFinish009 + * @tc.desc: Test frameNode OnLayoutFinish + * @tc.type: FUNC + */ +HWTEST_F(FrameNodeTestNg, OnLayoutFinish009, TestSize.Level1) +{ + /** + * @tc.steps: step1. set API20. + */ + int originApiVersion = AceApplicationInfo::GetInstance().GetApiTargetVersion(); + AceApplicationInfo::GetInstance().apiVersion_ = static_cast(PlatformVersion::VERSION_TWENTY); + + /** + * @tc.steps: step2. create frameNode. + */ + auto frameNode = FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, 1, AceType::MakeRefPtr(), true); + EXPECT_NE(frameNode->pattern_, nullptr); + + /** + * @tc.steps: step3. API20, test OnLayoutFinish. + * @tc.expected: result return true. + */ + bool needSyncRsNode = true; + DirtySwapConfig config; + frameNode->isActive_ = true; + frameNode->needSkipSyncGeometryNode_ = false; + auto layoutAlgorithmWrapper = AceType::MakeRefPtr(nullptr); + frameNode->layoutAlgorithm_ = layoutAlgorithmWrapper; + auto result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_TRUE(result); + + /** + * @tc.steps: step4. revert to the origin API. + */ + AceApplicationInfo::GetInstance().SetApiTargetVersion(originApiVersion); +} + +/** + * @tc.name: OnLayoutFinish010 + * @tc.desc: Test frameNode OnLayoutFinish + * @tc.type: FUNC + */ +HWTEST_F(FrameNodeTestNg, OnLayoutFinish010, TestSize.Level1) +{ + /** + * @tc.steps: step1. set API19. + */ + int originApiVersion = AceApplicationInfo::GetInstance().GetApiTargetVersion(); + AceApplicationInfo::GetInstance().apiVersion_ = static_cast(PlatformVersion::VERSION_NINETEEN); + + /** + * @tc.steps: step2. create frameNode. + */ + auto frameNode = FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, 1, AceType::MakeRefPtr(), true); + EXPECT_NE(frameNode->pattern_, nullptr); + + /** + * @tc.steps: step3. API19, test OnLayoutFinish. + * @tc.expected: result return true. + */ + bool needSyncRsNode = true; + DirtySwapConfig config; + frameNode->isActive_ = true; + frameNode->needSkipSyncGeometryNode_ = false; + auto layoutAlgorithmWrapper = AceType::MakeRefPtr(nullptr); + frameNode->layoutAlgorithm_ = layoutAlgorithmWrapper; + auto result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_TRUE(result); + + /** + * @tc.steps: step4. revert to the origin API. + */ + AceApplicationInfo::GetInstance().SetApiTargetVersion(originApiVersion); +} + +/** + * @tc.name: OnLayoutFinish011 + * @tc.desc: Test frameNode OnLayoutFinish + * @tc.type: FUNC + */ +HWTEST_F(FrameNodeTestNg, OnLayoutFinish011, TestSize.Level1) +{ + /** + * @tc.steps: step1. set API20. + */ + int originApiVersion = AceApplicationInfo::GetInstance().GetApiTargetVersion(); + AceApplicationInfo::GetInstance().apiVersion_ = static_cast(PlatformVersion::VERSION_TWENTY); + + /** + * @tc.steps: step2. create frameNode. + */ + auto frameNode = FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, 1, AceType::MakeRefPtr(), true); + EXPECT_NE(frameNode->pattern_, nullptr); + + /** + * @tc.steps: step3. needRerender true, test OnLayoutFinish. + * @tc.expected: result return true. + */ + bool needSyncRsNode = true; + DirtySwapConfig config; + frameNode->isActive_ = true; + frameNode->needSkipSyncGeometryNode_ = false; + auto layoutAlgorithmWrapper = AceType::MakeRefPtr(nullptr); + frameNode->layoutAlgorithm_ = layoutAlgorithmWrapper; + auto extensionHandler = AceType::MakeRefPtr(); + frameNode->extensionHandler_ = extensionHandler; + extensionHandler->needRender_ = true; + auto result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_TRUE(result); + + /** + * @tc.steps: step4. revert to the origin API. + */ + AceApplicationInfo::GetInstance().SetApiTargetVersion(originApiVersion); +} + +/** + * @tc.name: OnLayoutFinish012 + * @tc.desc: Test frameNode OnLayoutFinish + * @tc.type: FUNC + */ +HWTEST_F(FrameNodeTestNg, OnLayoutFinish012, TestSize.Level1) +{ + /** + * @tc.steps: step1. set API20. + */ + int originApiVersion = AceApplicationInfo::GetInstance().GetApiTargetVersion(); + AceApplicationInfo::GetInstance().apiVersion_ = static_cast(PlatformVersion::VERSION_TWENTY); + + /** + * @tc.steps: step2. create frameNode. + */ + auto frameNode = FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, 1, AceType::MakeRefPtr(), true); + EXPECT_NE(frameNode->pattern_, nullptr); + + /** + * @tc.steps: step3. needRerender false, drawModifier valid and not skipMeasure, test OnLayoutFinish. + * @tc.expected: result return true. + */ + bool needSyncRsNode = true; + DirtySwapConfig config; + frameNode->isActive_ = true; + frameNode->needSkipSyncGeometryNode_ = false; + auto layoutAlgorithmWrapper = AceType::MakeRefPtr(nullptr); + frameNode->layoutAlgorithm_ = layoutAlgorithmWrapper; + auto extensionHandler = AceType::MakeRefPtr(); + frameNode->extensionHandler_ = extensionHandler; + extensionHandler->needRender_ = false; + auto drawModifier = AceType::MakeRefPtr(); + extensionHandler->drawModifier_ = drawModifier; + layoutAlgorithmWrapper->skipMeasure_ = false; + auto result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_TRUE(result); + + /** + * @tc.steps: step4. needRerender false, drawModifier valid and skipMeasure, test OnLayoutFinish. + * @tc.expected: result return true. + */ + layoutAlgorithmWrapper = AceType::MakeRefPtr(nullptr); + frameNode->layoutAlgorithm_ = layoutAlgorithmWrapper; + layoutAlgorithmWrapper->skipMeasure_ = true; + PropertyChangeFlag propertyChangeFlag = PROPERTY_UPDATE_NORMAL; + frameNode->paintProperty_->propertyChangeFlag_ = propertyChangeFlag; + result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_TRUE(result); + + /** + * @tc.steps: step5. revert to the origin API. + */ + AceApplicationInfo::GetInstance().SetApiTargetVersion(originApiVersion); +} + +/** + * @tc.name: OnLayoutFinish013 + * @tc.desc: Test frameNode OnLayoutFinish + * @tc.type: FUNC + */ +HWTEST_F(FrameNodeTestNg, OnLayoutFinish013, TestSize.Level1) +{ + /** + * @tc.steps: step1. set API20. + */ + int originApiVersion = AceApplicationInfo::GetInstance().GetApiTargetVersion(); + AceApplicationInfo::GetInstance().apiVersion_ = static_cast(PlatformVersion::VERSION_TWENTY); + + /** + * @tc.steps: step2. create frameNode. + */ + auto frameNode = FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, 1, AceType::MakeRefPtr(), true); + EXPECT_NE(frameNode->pattern_, nullptr); + + /** + * @tc.steps: step3. needRerender false and CheckNeedRender true, test OnLayoutFinish. + * @tc.expected: result return true. + */ + bool needSyncRsNode = true; + DirtySwapConfig config; + frameNode->isActive_ = true; + frameNode->needSkipSyncGeometryNode_ = false; + auto layoutAlgorithmWrapper = AceType::MakeRefPtr(nullptr); + frameNode->layoutAlgorithm_ = layoutAlgorithmWrapper; + auto extensionHandler = AceType::MakeRefPtr(); + frameNode->extensionHandler_ = extensionHandler; + extensionHandler->needRender_ = false; + PropertyChangeFlag propertyChangeFlag = PROPERTY_UPDATE_RENDER; + frameNode->paintProperty_->propertyChangeFlag_ = propertyChangeFlag; + auto result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_TRUE(result); + + /** + * @tc.steps: step4. needRerender false and CheckNeedRender false, test OnLayoutFinish. + * @tc.expected: result return true. + */ + layoutAlgorithmWrapper = AceType::MakeRefPtr(nullptr); + frameNode->layoutAlgorithm_ = layoutAlgorithmWrapper; + propertyChangeFlag = PROPERTY_UPDATE_NORMAL; + frameNode->paintProperty_->propertyChangeFlag_ = propertyChangeFlag; + result = frameNode->OnLayoutFinish(needSyncRsNode, config); + EXPECT_TRUE(result); + + /** + * @tc.steps: step5. revert to the origin API. + */ + AceApplicationInfo::GetInstance().SetApiTargetVersion(originApiVersion); +} } // namespace OHOS::Ace::NG -- Gitee