From ea3311e14917bafb1499a428ef0baec04aa7790f Mon Sep 17 00:00:00 2001 From: zhoutianer Date: Thu, 13 Apr 2023 11:10:30 +0800 Subject: [PATCH 1/2] fix svg transform rotate with rotateCenter Signed-off-by: zhoutianer Change-Id: Ifca0de6415c3c98da4e87177e2a12bc576308a99 Signed-off-by: zhoutianer --- .../core/components/svg/svg_transform.cpp | 73 +++++----------- .../core/components/svg/svg_transform.h | 4 + .../test/unittest/svg/svg_transform_test.cpp | 87 ++++++++++++++----- .../core/components_ng/svg/parse/svg_node.cpp | 11 +-- 4 files changed, 91 insertions(+), 84 deletions(-) diff --git a/frameworks/core/components/svg/svg_transform.cpp b/frameworks/core/components/svg/svg_transform.cpp index 665889ebc7d..4fc83bb4459 100644 --- a/frameworks/core/components/svg/svg_transform.cpp +++ b/frameworks/core/components/svg/svg_transform.cpp @@ -32,6 +32,13 @@ const char TRANSFORM_TRANSLATE[] = "translate"; using namespace StringUtils; +void SvgTransform::ApplyRotationPivot(Matrix4& mat, float x, float y) +{ + // translate matrix to offset rotation center + // effect = translate(pivot) -> rotate(angle) -> translate(-pivot) + mat = Matrix4::CreateTranslate(x, y, 0) * mat * Matrix4::CreateTranslate(-x, -y, 0); +} + Matrix4 SvgTransform::CreateMatrix4(const std::string& transform) { auto retMat = Matrix4::CreateIdentity(); @@ -63,6 +70,9 @@ Matrix4 SvgTransform::CreateMatrix4(const std::string& transform) } } else if (type == TRANSFORM_ROTATE) { mat = Matrix4::CreateRotate(StringToFloat(numVec[0].c_str()), 0, 0, 1); + if (numVec.size() >= 3) { + ApplyRotationPivot(mat, StringToFloat(numVec[1]), StringToFloat(numVec[2])); + } } else if (type == TRANSFORM_SKEWX) { mat = Matrix4::CreateSkew(StringToFloat(numVec[0].c_str()), 0); } else if (type == TRANSFORM_SKEWY) { @@ -81,62 +91,15 @@ Matrix4 SvgTransform::CreateMatrix4(const std::string& transform) TransformInfo SvgTransform::CreateInfoFromString(const std::string& transform) { - auto retMat = Matrix4::CreateIdentity(); - std::vector attrs; - SplitStr(transform, ")", attrs); TransformInfo transformInfo; - for (auto& attr : attrs) { - std::string type = attr.substr(0, attr.find_first_of("(")); - std::string values = attr.substr(attr.find_first_of("(") + 1); - std::vector numVec; - std::string tag = (values.find(",") != std::string::npos) ? "," : " "; - SplitStr(values, tag, numVec); - if (numVec.empty()) { - continue; - } - - Matrix4 mat = Matrix4::CreateIdentity(); - TrimStr(attr); - if (type == TRANSFORM_TRANSLATE) { - if (numVec.size() == 1) { - mat = Matrix4::CreateTranslate(StringToFloat(numVec[0].c_str()), 0, 0); - } else { - mat = Matrix4::CreateTranslate(StringToFloat(numVec[0].c_str()), StringToFloat(numVec[1].c_str()), 0); - } - } else if (type == TRANSFORM_SCALE) { - if (numVec.size() == 1) { - mat = Matrix4::CreateScale(StringToFloat(numVec[0].c_str()), StringToFloat(numVec[0].c_str()), 1); - } else { - mat = Matrix4::CreateScale(StringToFloat(numVec[0].c_str()), StringToFloat(numVec[1].c_str()), 1); - } - } else if (type == TRANSFORM_ROTATE) { - mat = Matrix4::CreateRotate(StringToFloat(numVec[0].c_str()), 0, 0, 1); - if (numVec.size() >= 3) { - transformInfo.hasRotateCenter = true; - transformInfo.rotateCenter = Offset(StringToFloat(numVec[1]), StringToFloat(numVec[2])); - } - } else if (type == TRANSFORM_SKEWX) { - mat = Matrix4::CreateSkew(StringToFloat(numVec[0].c_str()), 0); - } else if (type == TRANSFORM_SKEWY) { - mat = Matrix4::CreateSkew(0, StringToFloat(numVec[0].c_str())); - } else if (type == TRANSFORM_MATRIX && numVec.size() == 6) { - mat = Matrix4::CreateMatrix2D(StringToFloat(numVec[0].c_str()), StringToFloat(numVec[1].c_str()), - StringToFloat(numVec[2].c_str()), StringToFloat(numVec[3].c_str()), - StringToFloat(numVec[4].c_str()), StringToFloat(numVec[5].c_str())); - } else { - continue; - } - retMat = retMat * mat; - } - transformInfo.matrix4 = retMat; + transformInfo.matrix4 = CreateMatrix4(transform); return transformInfo; } -TransformInfo SvgTransform::CreateInfoFromMap(const std::map>& transform) +Matrix4 SvgTransform::CreateMatrixFromMap(const std::map>& transform) { auto retMat = Matrix4::CreateIdentity(); auto mat = Matrix4::CreateIdentity(); - TransformInfo transformInfo; for (auto& [type, values] : transform) { if (values.empty()) { continue; @@ -148,8 +111,7 @@ TransformInfo SvgTransform::CreateInfoFromMap(const std::map= 3) { - transformInfo.hasRotateCenter = true; - transformInfo.rotateCenter = Offset(values[1], values[2]); + ApplyRotationPivot(mat, values[1], values[2]); } } else if (type == TRANSFORM_SKEW && values.size() >= 2) { mat = Matrix4::CreateSkew(values[0], values[1]); @@ -158,7 +120,13 @@ TransformInfo SvgTransform::CreateInfoFromMap(const std::map>& transform) +{ + TransformInfo transformInfo; + transformInfo.matrix4 = CreateMatrixFromMap(transform); return transformInfo; } @@ -322,4 +290,3 @@ bool SvgTransform::AlignmentFrame(const std::string& type, std::vector& f } } // namespace OHOS::Ace - diff --git a/frameworks/core/components/svg/svg_transform.h b/frameworks/core/components/svg/svg_transform.h index 9ef06c4e18c..3c67bcfc356 100644 --- a/frameworks/core/components/svg/svg_transform.h +++ b/frameworks/core/components/svg/svg_transform.h @@ -43,6 +43,7 @@ public: // { "scale", {1, 0.5} }, { "matrix", {1, 2, 3, 4, 5, 6} } }" static std::map> CreateMap(const std::string& transform); + static Matrix4 CreateMatrixFromMap(const std::map>& transform); static TransformInfo CreateInfoFromMap(const std::map>& transform); static bool SetProperty(const std::string& type, const std::vector& from, const std::vector& to, @@ -51,6 +52,9 @@ public: static bool AlignmentValues(const std::string& type, std::vector& from, std::vector& to); static bool AlignmentFrame(const std::string& type, std::vector& frame); + +private: + static void ApplyRotationPivot(Matrix4& mat, float x, float y); }; } // namespace OHOS::Ace diff --git a/frameworks/core/components/test/unittest/svg/svg_transform_test.cpp b/frameworks/core/components/test/unittest/svg/svg_transform_test.cpp index 7cb905e58ff..3efe1008862 100644 --- a/frameworks/core/components/test/unittest/svg/svg_transform_test.cpp +++ b/frameworks/core/components/test/unittest/svg/svg_transform_test.cpp @@ -51,16 +51,18 @@ public: /** * @tc.name: SvgTransformParse001 - * @tc.desc: Parse single param of tranform. + * @tc.desc: Parse single param of transform. * @tc.type: FUNC */ HWTEST_F(TransformParseTest, SvgTransformParse001, TestSize.Level0) { /** - * @tc.steps: step1. Parse single param of tranform. + * @tc.steps: step1. Parse single param of transform. * @tc.expected: step1. Result is in anticipation. */ - ASSERT_EQ(SvgTransform::CreateMatrix4("rotate(-10, 50, 100)"), Matrix4::CreateRotate(-10.0f, 0.0f, 0.0f, 1.0f)); + ASSERT_EQ(SvgTransform::CreateMatrix4("rotate(-10, 50, 100)"), Matrix4::CreateTranslate(50.0f, 100.0f, 0.0f) * + Matrix4::CreateRotate(-10.0f, 0.0f, 0.0f, 1.0f) * + Matrix4::CreateTranslate(-50.0f, -100.0f, 0.0f)); ASSERT_EQ(SvgTransform::CreateMatrix4("translate(10)"), Matrix4::CreateTranslate(10.0f, 0.0f, 0.0f)); ASSERT_EQ(SvgTransform::CreateMatrix4("translate(0, 9)"), Matrix4::CreateTranslate(0.0f, 9.0f, 0.0f)); ASSERT_EQ(SvgTransform::CreateMatrix4("translate(-36, 45.5)"), Matrix4::CreateTranslate(-36.0f, 45.5f, 0.0f)); @@ -73,7 +75,7 @@ HWTEST_F(TransformParseTest, SvgTransformParse001, TestSize.Level0) /** * @tc.name: SvgTransformParse002 - * @tc.desc: Parse translate param of tranform. + * @tc.desc: Parse translate param of transform. * @tc.type: FUNC */ HWTEST_F(TransformParseTest, SvgTransformParse002, TestSize.Level0) @@ -91,7 +93,7 @@ HWTEST_F(TransformParseTest, SvgTransformParse002, TestSize.Level0) /** * @tc.name: SvgTransformParse003 - * @tc.desc: Parse skew param of tranform. + * @tc.desc: Parse skew param of transform. * @tc.type: FUNC */ HWTEST_F(TransformParseTest, SvgTransformParse003, TestSize.Level0) @@ -106,7 +108,7 @@ HWTEST_F(TransformParseTest, SvgTransformParse003, TestSize.Level0) /** * @tc.name: SvgTransformParse004 - * @tc.desc: Parse completed param of tranform. + * @tc.desc: Parse completed param of transform. * @tc.type: FUNC */ HWTEST_F(TransformParseTest, SvgTransformParse004, TestSize.Level0) @@ -117,17 +119,16 @@ HWTEST_F(TransformParseTest, SvgTransformParse004, TestSize.Level0) */ auto mat = SvgTransform::CreateMatrix4( "rotate(-10, 50, 100) translate(-36, 45.5) skewX(40) skewY(50) scale(1, 0.5) matrix(1, 2, 3, 4, 5, 6)"); - ASSERT_EQ(mat, Matrix4::CreateRotate(-10.0f, 0.0f, 0.0f, 1.0f) * - Matrix4::CreateTranslate(-36.0f, 45.5f, 0.0f) * - Matrix4::CreateSkew(40.0f, 0.0f) * - Matrix4::CreateSkew(0.0f, 50.0f) * - Matrix4::CreateScale(1.0f, 0.5f, 1.0f) * - Matrix4::CreateMatrix2D(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f)); + ASSERT_EQ(mat, Matrix4::CreateTranslate(50, 100, 0) * Matrix4::CreateRotate(-10.0f, 0.0f, 0.0f, 1.0f) * + Matrix4::CreateTranslate(-50, -100, 0) * Matrix4::CreateTranslate(-36.0f, 45.5f, 0.0f) * + Matrix4::CreateSkew(40.0f, 0.0f) * Matrix4::CreateSkew(0.0f, 50.0f) * + Matrix4::CreateScale(1.0f, 0.5f, 1.0f) * + Matrix4::CreateMatrix2D(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f)); } /** * @tc.name: SvgTransformParse005 - * @tc.desc: Parse completed param of tranform. + * @tc.desc: Parse completed param of transform. * @tc.type: FUNC */ HWTEST_F(TransformParseTest, SvgTransformParse005, TestSize.Level0) @@ -142,37 +143,32 @@ HWTEST_F(TransformParseTest, SvgTransformParse005, TestSize.Level0) auto iter = transform.find("rotate"); ASSERT_TRUE(iter != transform.end()); if (iter != transform.end()) { - std::vector rotation = {-10.0f, 50.0f, 100.0f}; + std::vector rotation = { -10.0f, 50.0f, 100.0f }; ASSERT_TRUE(CompareVectorFloat(iter->second, rotation)); } iter = transform.find("translate"); ASSERT_TRUE(iter != transform.end()); if (iter != transform.end()) { - std::vector translate = {-36.0f, 45.5f, 0.0f}; + std::vector translate = { -36.0f, 45.5f, 0.0f }; ASSERT_TRUE(CompareVectorFloat(iter->second, translate)); } iter = transform.find("skew"); ASSERT_TRUE(iter != transform.end()); if (iter != transform.end()) { - std::vector skew = {40.0f, 50.0f}; + std::vector skew = { 40.0f, 50.0f }; ASSERT_TRUE(CompareVectorFloat(iter->second, skew)); } iter = transform.find("matrix"); ASSERT_TRUE(iter != transform.end()); if (iter != transform.end()) { - std::vector matrix = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}; + std::vector matrix = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f }; ASSERT_TRUE(CompareVectorFloat(iter->second, matrix)); } - - auto transformInfo = SvgTransform::CreateInfoFromMap(transform); - ASSERT_TRUE(transformInfo.hasRotateCenter); - ASSERT_EQ(transformInfo.rotateCenter, Offset(50.0f, 100.0f)); } - /** * @tc.name: SvgTransformAlignment001 * @tc.desc: Alignment attr from and to. @@ -261,7 +257,7 @@ HWTEST_F(TransformParseTest, SvgTransformAlignment002, TestSize.Level0) */ std::vector frameScale = { 2.0 }; ASSERT_TRUE(SvgTransform::AlignmentFrame("scale", frameScale)); - ASSERT_TRUE(CompareVectorFloat((frameScale), std::vector({2.0f, 2.0f}))); + ASSERT_TRUE(CompareVectorFloat((frameScale), std::vector({ 2.0f, 2.0f }))); frameScale = {}; ASSERT_FALSE(SvgTransform::AlignmentFrame("scale", frameScale)); @@ -300,4 +296,49 @@ HWTEST_F(TransformParseTest, SvgTransformAlignment002, TestSize.Level0) ASSERT_FALSE(SvgTransform::AlignmentFrame("translate", frameTranslate)); } +/** + * @tc.name: SvgTransformRotation001 + * @tc.desc: Rotate with transform center. + * @tc.type: FUNC + */ +HWTEST_F(TransformParseTest, SvgTransformRotation001, TestSize.Level0) +{ + auto mat = SvgTransform::CreateMatrix4("rotate(45, 10, 10)"); + auto mat2 = SvgTransform::CreateMatrix4("translate(10, 10) rotate(45) translate(-10 -10)"); + ASSERT_EQ(mat, mat2); +} + +/** + * @tc.name: SvgTransformMap001 + * @tc.desc: Test create matrix from map. + * @tc.type: FUNC + */ +HWTEST_F(TransformParseTest, SvgTransformMap001, TestSize.Level0) +{ + auto transform = SvgTransform::CreateMap("rotate(-10, 50, 100)"); + auto info = SvgTransform::CreateInfoFromMap(transform); + ASSERT_EQ(info.matrix4, Matrix4::CreateTranslate(50, 100, 0) * Matrix4::CreateRotate(-10, 0, 0, 1) * + Matrix4::CreateTranslate(-50, -100, 0)); + + transform = SvgTransform::CreateMap("translate(-36, 45.5)"); + auto matrix = SvgTransform::CreateMatrixFromMap(transform); + ASSERT_EQ(matrix, Matrix4::CreateTranslate(-36, 45.5, 0)); + + transform = SvgTransform::CreateMap("skewX(40)"); + matrix = SvgTransform::CreateMatrixFromMap(transform); + ASSERT_EQ(matrix, Matrix4::CreateSkew(40, 0)); + + transform = SvgTransform::CreateMap("skewY(50)"); + matrix = SvgTransform::CreateMatrixFromMap(transform); + ASSERT_EQ(matrix, Matrix4::CreateSkew(0, 50)); + + transform = SvgTransform::CreateMap("scale(1, 0.5)"); + matrix = SvgTransform::CreateMatrixFromMap(transform); + ASSERT_EQ(matrix, Matrix4::CreateScale(1, 0.5, 1)); + + // AnimateTransform that uses map doesn't support matrix + transform = SvgTransform::CreateMap("matrix(1, 2, 3, 4, 5, 6)"); + matrix = SvgTransform::CreateMatrixFromMap(transform); + ASSERT_EQ(matrix, Matrix4::CreateIdentity()); +} } // namespace OHOS::Ace diff --git a/frameworks/core/components_ng/svg/parse/svg_node.cpp b/frameworks/core/components_ng/svg/parse/svg_node.cpp index 4fee7bb118a..dbfdf466f14 100644 --- a/frameworks/core/components_ng/svg/parse/svg_node.cpp +++ b/frameworks/core/components_ng/svg/parse/svg_node.cpp @@ -227,14 +227,9 @@ void SvgNode::OnMask(RSCanvas& canvas, const Size& viewPort) void SvgNode::OnTransform(RSCanvas& canvas, const Size& viewPort) { - auto transformInfo = (animateTransform_.empty()) ? SvgTransform::CreateInfoFromString(transform_) - : SvgTransform::CreateInfoFromMap(animateTransform_); - if (transformInfo.hasRotateCenter) { - transformInfo.matrix4 = - RenderTransform::GetTransformByOffset(transformInfo.matrix4, transformInfo.rotateCenter); - // maybe should process attr transformOrigin - } - skCanvas_->concat(FlutterSvgPainter::ToSkMatrix(transformInfo.matrix4)); + auto matrix = (animateTransform_.empty()) ? SvgTransform::CreateMatrix4(transform_) + : SvgTransform::CreateMatrixFromMap(animateTransform_); + skCanvas_->concat(FlutterSvgPainter::ToSkMatrix(matrix)); } double SvgNode::ConvertDimensionToPx(const Dimension& value, const Size& viewPort, SvgLengthType type) const -- Gitee From ba23bc2fc51b17e9865760e73338ec9f6db158a5 Mon Sep 17 00:00:00 2001 From: Sarath Singapati Date: Thu, 16 Mar 2023 18:02:54 +0800 Subject: [PATCH 2/2] Custom animatable property creation and update handling with number type. Signed-off-by: Sarath Singapati Change-Id: I5855dfb3d71323f0c33314fbeb2183218ef90432 --- .../jsview/js_view_abstract.cpp | 55 +++++++++++++++++++ .../jsview/js_view_abstract.h | 3 + .../jsview/models/view_abstract_model_impl.h | 4 ++ frameworks/core/components_ng/base/BUILD.gn | 5 ++ .../core/components_ng/base/view_abstract.cpp | 32 +++++++++++ .../core/components_ng/base/view_abstract.h | 7 +++ .../components_ng/base/view_abstract_model.h | 5 ++ .../base/view_abstract_model_ng.h | 9 +++ .../render/adapter/rosen_modifier_adapter.cpp | 49 +++++++++++++++++ .../render/adapter/rosen_modifier_adapter.h | 19 +++++++ .../render/adapter/rosen_render_context.cpp | 13 +++++ .../render/adapter/rosen_render_context.h | 3 + .../components_ng/render/render_context.h | 4 ++ 13 files changed, 208 insertions(+) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp index 46ded66faf4..3d12b6c85f0 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp @@ -4674,7 +4674,10 @@ void JSViewAbstract::JSBind() JSClass::StaticMethod("hitTestBehavior", &JSViewAbstract::JsHitTestBehavior); JSClass::StaticMethod("keyboardShortcut", &JSViewAbstract::JsKeyboardShortcut); JSClass::StaticMethod("allowDrop", &JSViewAbstract::JsAllowDrop); + JSClass::StaticMethod("createAnimatableProperty", &JSViewAbstract::JSCreateAnimatableProperty); + JSClass::StaticMethod("updateAnimatableProperty", &JSViewAbstract::JSUpdateAnimatableProperty); } + void JSViewAbstract::JsAllowDrop(const JSCallbackInfo& info) { if (!info[0]->IsArray()) { @@ -5297,4 +5300,56 @@ void JSViewAbstract::JsKeyboardShortcut(const JSCallbackInfo& info) ViewAbstractModel::GetInstance()->SetKeyboardShortcut(value, keys, nullptr); } +void JSViewAbstract::JSCreateAnimatableProperty(const JSCallbackInfo& info) +{ + if (info.Length() != 3 || !info[0]->IsString()) { + LOGE("JSCreateAnimatableProperty: The arg is invalid."); + return; + } + + std::string propertyName = info[0]->ToString(); + if (info[1]->IsNumber()) { + float numValue = info[1]->ToNumber(); + JSRef callback = info[2]; + if (!callback->IsFunction()) { + LOGE("JSCreateAnimatableProperty: callback function type is invalid."); + return; + } + std::function onCallbackEvent; + RefPtr jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(callback)); + onCallbackEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), + id = Container::CurrentId()](const float val) { + ContainerScope scope(id); + JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); + LOGD("onCallbackEvent(number) execute js func. val: %f", val); + auto newJSVal = JSRef::Make(ToJSValue(val)); + func->ExecuteJS(1, &newJSVal); + }; + ViewAbstractModel::GetInstance()->CreateAnimatableProperty(propertyName, numValue, onCallbackEvent); + + } else if (info[1]->IsObject()) { + LOGD("Object type (AnimatableArithmetic) to be handled."); + } else { + LOGE("JSCreateAnimatableProperty: The value param type is invalid."); + } +} + +void JSViewAbstract::JSUpdateAnimatableProperty(const JSCallbackInfo& info) +{ + if (info.Length() != 2 || !info[0]->IsString()) { + LOGE("JSUpdateAnimatableProperty: The arg is invalid."); + return; + } + + std::string propertyName = info[0]->ToString(); + float numValue = 0.0; + if (info[1]->IsNumber()) { + numValue = info[1]->ToNumber(); + ViewAbstractModel::GetInstance()->UpdateAnimatableProperty(propertyName, numValue); + } else if (info[1]->IsObject()) { + LOGD("Object type (RSAnimatableArithmetic) to be handled"); + } else { + LOGE("JSUpdateAnimatableProperty: The value param type is invalid."); + } +} } // namespace OHOS::Ace::Framework diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h index 7ed0f139eb5..032868b90e9 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h @@ -240,6 +240,9 @@ public: static void JsAccessibilityImportance(const std::string& importance); static void JsAllowDrop(const JSCallbackInfo& info); + static void JSCreateAnimatableProperty(const JSCallbackInfo& info); + static void JSUpdateAnimatableProperty(const JSCallbackInfo& info); + static void ParseMenuOptions( const JSCallbackInfo& info, const JSRef& jsArray, std::vector& items); diff --git a/frameworks/bridge/declarative_frontend/jsview/models/view_abstract_model_impl.h b/frameworks/bridge/declarative_frontend/jsview/models/view_abstract_model_impl.h index 209c2279bbd..9c7c6fb0513 100644 --- a/frameworks/bridge/declarative_frontend/jsview/models/view_abstract_model_impl.h +++ b/frameworks/bridge/declarative_frontend/jsview/models/view_abstract_model_impl.h @@ -184,6 +184,10 @@ public: void SetForegroundColor(const Color& color) override {} void SetForegroundColorStrategy(const ForegroundColorStrategy& strategy) override {} void SetAllowDrop(const std::set& allowDrop) override {} + + void CreateAnimatableProperty(const std::string& propertyName, float value, + const std::function& onCallbackEvent) override {}; + void UpdateAnimatableProperty(const std::string& propertyName, float value) override {}; }; } // namespace OHOS::Ace::Framework diff --git a/frameworks/core/components_ng/base/BUILD.gn b/frameworks/core/components_ng/base/BUILD.gn index 8f8efbc5513..f2dfba3789a 100644 --- a/frameworks/core/components_ng/base/BUILD.gn +++ b/frameworks/core/components_ng/base/BUILD.gn @@ -26,6 +26,11 @@ build_component_ng("base_ng") { "view_partial_update_model_ng.cpp", "view_stack_processor.cpp", ] + + if (is_standard_system) { + deps = [ "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client" ] + } + component_ng_deps = [ "animation_ng", "event_ng", diff --git a/frameworks/core/components_ng/base/view_abstract.cpp b/frameworks/core/components_ng/base/view_abstract.cpp index 3fead17907d..29146de9db8 100644 --- a/frameworks/core/components_ng/base/view_abstract.cpp +++ b/frameworks/core/components_ng/base/view_abstract.cpp @@ -32,12 +32,16 @@ #include "core/components_ng/pattern/option/option_paint_property.h" #include "core/components_ng/pattern/text/span_node.h" #include "core/components_ng/property/calc_length.h" +#include "core/components_ng/render/adapter/rosen_modifier_adapter.h" +#include "core/components_ng/render/adapter/rosen_render_context.h" #include "core/image/image_source_info.h" #include "core/pipeline_ng/pipeline_context.h" #include "core/pipeline_ng/ui_task_scheduler.h" namespace OHOS::Ace::NG { +std::unordered_map ViewAbstract::customAnimatablePropertyIDMap_; + namespace { // common function to bind menu @@ -1346,4 +1350,32 @@ void ViewAbstract::SetKeyboardShortcut( eventManager->AddKeyboardShortcutNode(WeakPtr(frameNode)); } +void ViewAbstract::CreateAnimatableProperty(const std::string& propertyName, float value, + const std::function& onCallbackEvent) +{ + LOGD("ViewAbstract::CreateAnimatableProperty()"); + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto context = frameNode->GetRenderContext(); + CHECK_NULL_VOID(context); + uint64_t propertyId = context->CreateAnimatableProperty(propertyName, value, onCallbackEvent); + customAnimatablePropertyIDMap_.emplace(propertyName, propertyId); +} + +void ViewAbstract::UpdateAnimatableProperty(const std::string& propertyName, float value) +{ + LOGD("UpdateAnimatableProperty() propertyName: %s", propertyName.c_str()); + const auto& iter = customAnimatablePropertyIDMap_.find(propertyName); + if (iter == customAnimatablePropertyIDMap_.end()) { + LOGE("property not found."); + return; + } + uint64_t propertyId = iter->second; + std::shared_ptr nodeModifier = GetCustomAnimatableModifier(propertyId); + if (!nodeModifier) { + LOGE("CustomAnimatableModifier is null"); + return; + } + nodeModifier->SetNumber(value); +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/base/view_abstract.h b/frameworks/core/components_ng/base/view_abstract.h index 89f49bd81d7..81172750dfe 100644 --- a/frameworks/core/components_ng/base/view_abstract.h +++ b/frameworks/core/components_ng/base/view_abstract.h @@ -243,8 +243,15 @@ public: static void SetForegroundColor(const Color& color); static void SetForegroundColorStrategy(const ForegroundColorStrategy& strategy); + // custom animatable property + static void CreateAnimatableProperty(const std::string& propertyName, float value, + const std::function& onCallbackEvent); + static void UpdateAnimatableProperty(const std::string& propertyName, float value); + private: static void AddDragFrameNodeToManager(); + + static std::unordered_map customAnimatablePropertyIDMap_; }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/base/view_abstract_model.h b/frameworks/core/components_ng/base/view_abstract_model.h index dfb5e42c3c5..e0d6bd0b6a9 100644 --- a/frameworks/core/components_ng/base/view_abstract_model.h +++ b/frameworks/core/components_ng/base/view_abstract_model.h @@ -232,6 +232,11 @@ public: virtual void SetForegroundColor(const Color& color) = 0; virtual void SetForegroundColorStrategy(const ForegroundColorStrategy& strategy) = 0; + // custom animation properties + virtual void CreateAnimatableProperty(const std::string& propertyName, float value, + const std::function& onCallbackEvent) = 0; + virtual void UpdateAnimatableProperty(const std::string& propertyName, float value) = 0; + private: static std::unique_ptr instance_; }; diff --git a/frameworks/core/components_ng/base/view_abstract_model_ng.h b/frameworks/core/components_ng/base/view_abstract_model_ng.h index 7d6e1e13636..ba401d111e6 100644 --- a/frameworks/core/components_ng/base/view_abstract_model_ng.h +++ b/frameworks/core/components_ng/base/view_abstract_model_ng.h @@ -730,6 +730,15 @@ public: { ViewAbstract::SetForegroundColorStrategy(strategy); } + + void CreateAnimatableProperty(const std::string& propertyName, float value, + const std::function& onCallbackEvent) override { + ViewAbstract::CreateAnimatableProperty(propertyName, value, onCallbackEvent); + } + + void UpdateAnimatableProperty(const std::string& propertyName, float value) override { + ViewAbstract::UpdateAnimatableProperty(propertyName, value); + } }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/render/adapter/rosen_modifier_adapter.cpp b/frameworks/core/components_ng/render/adapter/rosen_modifier_adapter.cpp index b9ca9ec462f..6cf34460f35 100644 --- a/frameworks/core/components_ng/render/adapter/rosen_modifier_adapter.cpp +++ b/frameworks/core/components_ng/render/adapter/rosen_modifier_adapter.cpp @@ -140,4 +140,53 @@ void OverlayModifierAdapter::AttachProperties() } } } + +void AddCustomAnimatableModifier(std::shared_ptr modifier) +{ + LOGD("AddCustomAnimatableModifier()"); + CHECK_NULL_VOID(modifier); + std::lock_guard lock(g_ModifiersMapLock); + g_ModifiersMap.emplace(modifier->GetPropertyId(), modifier); +} + +std::shared_ptr GetCustomAnimatableModifier(uint64_t propertyId) +{ + LOGD("GetCustomAnimatableModifier()"); + std::lock_guard lock(g_ModifiersMapLock); + const auto& iter = g_ModifiersMap.find(propertyId); + if (iter != g_ModifiersMap.end()) { + LOGD("CustomAnimatableModifier found"); + return std::static_pointer_cast(iter->second); + } + LOGE("CustomAnimatableModifier not found"); + return nullptr; +} + +void CustomAnimatableModifier::Modify(RSNode& target) const +{ + LOGD("CustomAnimatableModifier::Modifier()"); +} + +void CustomAnimatableModifier::SetNumberData(float value, const std::function& callback) +{ + LOGD("SetNumberData: %f", value); + if (numberData_ == nullptr) { + numberData_ = std::make_shared>(value); + numberData_->SetUpdateCallback(callback); + AttachProperty(numberData_); + } else { + numberData_->Set(value); + } +} + +void CustomAnimatableModifier::SetNumber(float value) +{ + LOGD("SetNumber: %f", value); + if (numberData_ != nullptr) { + numberData_->Set(value); + } else { + LOGE("animatable property is null!"); + } +} + } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/render/adapter/rosen_modifier_adapter.h b/frameworks/core/components_ng/render/adapter/rosen_modifier_adapter.h index edfd35d201d..386bf6f752c 100644 --- a/frameworks/core/components_ng/render/adapter/rosen_modifier_adapter.h +++ b/frameworks/core/components_ng/render/adapter/rosen_modifier_adapter.h @@ -46,6 +46,7 @@ template using RSAnimatableArithmetic = Rosen::RSAnimatableArithmetic; using RSContentStyleModifier = Rosen::RSContentStyleModifier; using RSOverlayStyleModifier = Rosen::RSOverlayStyleModifier; +using RSNodeModifier = Rosen::RSNodeModifier; using RSDrawingContext = Rosen::RSDrawingContext; using RSPropertyBase = Rosen::RSPropertyBase; @@ -90,6 +91,24 @@ private: ACE_DISALLOW_COPY_AND_MOVE(OverlayModifierAdapter); }; +class CustomAnimatableModifier : public RSNodeModifier { +public: + CustomAnimatableModifier() = default; + virtual ~CustomAnimatableModifier() = default; + void Modify(RSNode& target) const override; + void SetNumberData(float value, const std::function& callback); + void SetNumber(float value); + +private: + std::shared_ptr> numberData_; + //std::shared_ptr> animatableArithmeticData_; + + ACE_DISALLOW_COPY_AND_MOVE(CustomAnimatableModifier); +}; + +void AddCustomAnimatableModifier(std::shared_ptr modifier); +std::shared_ptr GetCustomAnimatableModifier(uint64_t propertyId); + } // namespace OHOS::Ace::NG #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_RENDER_ADAPTER_MODIFIER_ADAPTER_H diff --git a/frameworks/core/components_ng/render/adapter/rosen_render_context.cpp b/frameworks/core/components_ng/render/adapter/rosen_render_context.cpp index b88957d46a9..93e8d65da63 100644 --- a/frameworks/core/components_ng/render/adapter/rosen_render_context.cpp +++ b/frameworks/core/components_ng/render/adapter/rosen_render_context.cpp @@ -2165,4 +2165,17 @@ void RosenRenderContext::SetActualForegroundColor(const Color& value) RequestNextFrame(); } +uint64_t RosenRenderContext::CreateAnimatableProperty(const std::string& propertyName, float value, + const std::function& onCallbackEvent) +{ + LOGD("RosenRenderContext::CreateAnimatableProperty() propertyName: %s, value: %f", propertyName.c_str(), value); + auto rsNode = GetRSNode(); + CHECK_NULL_RETURN(rsNode, 0); + std::shared_ptr nodeModifier = std::make_shared(); + // Should be added before setting the number. + rsNode->AddModifier(nodeModifier); + nodeModifier->SetNumberData(value, onCallbackEvent); + AddCustomAnimatableModifier(nodeModifier); + return nodeModifier->GetPropertyId(); +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/render/adapter/rosen_render_context.h b/frameworks/core/components_ng/render/adapter/rosen_render_context.h index 2a7ed1a3e1e..9db65de8482 100644 --- a/frameworks/core/components_ng/render/adapter/rosen_render_context.h +++ b/frameworks/core/components_ng/render/adapter/rosen_render_context.h @@ -215,6 +215,9 @@ public: RefPtr GetThumbnailPixelMap() override; void SetActualForegroundColor(const Color& value) override; + uint64_t CreateAnimatableProperty(const std::string& propertyName, float value, + const std::function& onCallbackEvent) override; + private: void OnBackgroundImageUpdate(const ImageSourceInfo& src) override; void OnBackgroundImageRepeatUpdate(const ImageRepeat& imageRepeat) override; diff --git a/frameworks/core/components_ng/render/render_context.h b/frameworks/core/components_ng/render/render_context.h index 5c2bf380450..28de194be07 100644 --- a/frameworks/core/components_ng/render/render_context.h +++ b/frameworks/core/components_ng/render/render_context.h @@ -248,6 +248,10 @@ public: virtual void OnSphericalEffectUpdate(double radio) {} virtual void OnPixelStretchEffectUpdate(const PixStretchEffectOption& option) {} virtual void OnLightUpEffectUpdate(double radio) {} + + virtual uint64_t CreateAnimatableProperty(const std::string& propertyName, float value, + const std::function& onCallbackEvent) = 0; + ACE_DEFINE_PROPERTY_ITEM_FUNC_WITHOUT_GROUP(SphericalEffect, double); ACE_DEFINE_PROPERTY_ITEM_FUNC_WITHOUT_GROUP(PixelStretchEffect, PixStretchEffectOption); ACE_DEFINE_PROPERTY_ITEM_FUNC_WITHOUT_GROUP(LightUpEffect, double); -- Gitee