From 83b0f665d3885b3f7249c7f2ba38c292dc12d4f8 Mon Sep 17 00:00:00 2001 From: jyj-0306 Date: Fri, 15 Mar 2024 17:51:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0removeSpan=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0&&=E4=BD=BF=E8=83=BD=E5=B1=9E=E6=80=A7=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=E4=B8=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: jyj-0306 Change-Id: I9944af029379b1ed7e4114c39d268002e97f8694 --- .../bridge/declarative_frontend/BUILD.gn | 4 + .../engine/jsEnumStyle.js | 64 ++++++----- .../engine/jsi/jsi_view_register_impl.cpp | 8 ++ .../engine/jsi/jsi_view_register_impl_ng.cpp | 5 + .../declarative_frontend/jsview/js_text.cpp | 18 ++- .../jsview/models/text_model_impl.h | 1 + .../style_string/js_span_object.cpp | 9 +- .../style_string/js_span_object.h | 9 +- .../style_string/js_span_string.cpp | 105 ++++++++++++------ .../style_string/js_span_string.h | 6 +- .../core/components_ng/pattern/BUILD.gn | 3 + .../pattern/text/span/mutable_span_string.cpp | 17 +-- .../pattern/text/span/mutable_span_string.h | 2 +- .../pattern/text/span/span_object.cpp | 74 +++++++++++- .../pattern/text/span/span_object.h | 19 +++- .../pattern/text/span/span_string.cpp | 47 ++++---- .../pattern/text/span/span_string.h | 14 +-- .../components_ng/pattern/text/span_node.cpp | 6 +- .../pattern/text/text_content_modifier.h | 2 +- .../components_ng/pattern/text/text_model.h | 1 + .../pattern/text/text_model_ng.cpp | 17 +++ .../pattern/text/text_model_ng.h | 1 + .../pattern/text/text_pattern.cpp | 53 ++++++++- .../components_ng/pattern/text/text_pattern.h | 27 ++++- test/unittest/BUILD.gn | 3 + 25 files changed, 381 insertions(+), 134 deletions(-) diff --git a/frameworks/bridge/declarative_frontend/BUILD.gn b/frameworks/bridge/declarative_frontend/BUILD.gn index c0fe17ac035..fcf99143e1f 100644 --- a/frameworks/bridge/declarative_frontend/BUILD.gn +++ b/frameworks/bridge/declarative_frontend/BUILD.gn @@ -323,6 +323,8 @@ template("declarative_js_engine") { "jsview/menu/js_context_menu.cpp", "jsview/scroll_bar/js_scroll_bar.cpp", "sharedata/js_share_data.cpp", + "style_string/js_span_object.cpp", + "style_string/js_span_string.cpp", "view_stack_processor.cpp", # Models implemenations for classic fw @@ -823,6 +825,8 @@ template("declarative_js_engine_ng") { "jsview/js_water_flow_sections.cpp", "jsview/menu/js_context_menu.cpp", "jsview/scroll_bar/js_scroll_bar.cpp", + "style_string/js_span_object.cpp", + "style_string/js_span_string.cpp", ] sources += [ diff --git a/frameworks/bridge/declarative_frontend/engine/jsEnumStyle.js b/frameworks/bridge/declarative_frontend/engine/jsEnumStyle.js index 4e1979e5577..c5c2dea36ef 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsEnumStyle.js +++ b/frameworks/bridge/declarative_frontend/engine/jsEnumStyle.js @@ -348,7 +348,7 @@ var TextDecorationStyle; TextDecorationStyle[TextDecorationStyle["DOTTED"] = 2] = "DOTTED"; TextDecorationStyle[TextDecorationStyle["DASHED"] = 3] = "DASHED"; TextDecorationStyle[TextDecorationStyle["WAVY"] = 4] = "WAVY"; -})(TextDecorationStyle || (TextDecorationStyle= {})); +})(TextDecorationStyle || (TextDecorationStyle = {})); var TextDecorationType; (function (TextDecorationType) { @@ -933,13 +933,13 @@ var TitleHeight; })(TitleHeight || (TitleHeight = {})); var NavDestinationMode; -(function(NavDestinationMode) { +(function (NavDestinationMode) { NavDestinationMode[NavDestinationMode["STANDARD"] = 0] = "STANDARD"; NavDestinationMode[NavDestinationMode["DIALOG"] = 1] = "DIALOG"; }(NavDestinationMode || (NavDestinationMode = {}))); let NavigationOperation; -(function(NavigationOperation) { +(function (NavigationOperation) { NavigationOperation[NavigationOperation.PUSH = 1] = "PUSH"; NavigationOperation[NavigationOperation.POP = 2] = "POP"; NavigationOperation[NavigationOperation.REPLACE = 3] = "REPLACE"; @@ -1393,17 +1393,17 @@ var GestureJudgeResult; var GestureControl; (function (GestureControl) { - let GestureType; - (function (GestureType) { - GestureType[GestureType["TAP_GESTURE"] = 0] = "TAP_GESTURE"; - GestureType[GestureType["LONG_PRESS_GESTURE"] = 1] = "LONG_PRESS_GESTURE"; - GestureType[GestureType["PAN_GESTURE"] = 2] = "PAN_GESTURE"; - GestureType[GestureType["PINCH_GESTURE"] = 3] = "PINCH_GESTURE"; - GestureType[GestureType["SWIPE_GESTURE"] = 4] = "SWIPE_GESTURE"; - GestureType[GestureType["ROTATION_GESTURE"] = 5] = "ROTATION_GESTURE"; - GestureType[GestureType["DRAG"] = 6] = "DRAG"; - GestureType[GestureType["CLICK"] = 7] = "CLICK"; - })(GestureType = GestureControl.GestureType || (GestureControl.GestureType = {})); + let GestureType; + (function (GestureType) { + GestureType[GestureType["TAP_GESTURE"] = 0] = "TAP_GESTURE"; + GestureType[GestureType["LONG_PRESS_GESTURE"] = 1] = "LONG_PRESS_GESTURE"; + GestureType[GestureType["PAN_GESTURE"] = 2] = "PAN_GESTURE"; + GestureType[GestureType["PINCH_GESTURE"] = 3] = "PINCH_GESTURE"; + GestureType[GestureType["SWIPE_GESTURE"] = 4] = "SWIPE_GESTURE"; + GestureType[GestureType["ROTATION_GESTURE"] = 5] = "ROTATION_GESTURE"; + GestureType[GestureType["DRAG"] = 6] = "DRAG"; + GestureType[GestureType["CLICK"] = 7] = "CLICK"; + })(GestureType = GestureControl.GestureType || (GestureControl.GestureType = {})); })(GestureControl || (GestureControl = {})); class SubTabBarStyle { @@ -1441,7 +1441,7 @@ class SubTabBarStyle { } class DrawModifier { - invalidate() {} + invalidate() { } } class ProgressMask { @@ -1802,7 +1802,7 @@ class NavPathStack { let promise = this.nativeStack?.onPushDestination(info); if (!promise) { this.pathArray.pop(); - return new Promise((resolve, reject)=>{ + return new Promise((resolve, reject) => { reject({ message: 'Internal error.', code: 100001 }); }) } @@ -1833,7 +1833,7 @@ class NavPathStack { let promise = this.nativeStack?.onPushDestination(info); if (!promise) { this.pathArray.pop(); - promise = new Promise((resolve, reject)=>{ + promise = new Promise((resolve, reject) => { reject({ message: 'Internal error.', code: 100001 }); }) } @@ -2006,7 +2006,7 @@ class NavPathStack { let tempArray = this.pathArray.slice(0); this.removeArray = []; this.pathArray = []; - for (let index = 0 ; index < tempArray.length ; index++) { + for (let index = 0; index < tempArray.length; index++) { if (tempArray[index] && !indexes.includes(index)) { this.pathArray.push(tempArray[index]); } else { @@ -2590,12 +2590,12 @@ var ImageAnalyzerType; })(ImageAnalyzerType || (ImageAnalyzerType = {})); function wrapBuilder(builder) { - return new WrappedBuilder(builder); + return new WrappedBuilder(builder); } class WrappedBuilder { - constructor(builder) { - this.builder = builder; - } + constructor(builder) { + this.builder = builder; + } } let TextSpanType; @@ -2626,16 +2626,16 @@ let RenderMode; })(RenderMode || (RenderMode = {})); let ButtonRole; -(function (ButtonRole){ +(function (ButtonRole) { ButtonRole['NORMAL'] = 0; ButtonRole['ERROR'] = 1; })(ButtonRole || (ButtonRole = {})); let MenuPolicy; (function (MenuPolicy) { - MenuPolicy['DEFAULT'] = 0; - MenuPolicy['NEVER'] = 1; - MenuPolicy['ALWAYS'] = 2; + MenuPolicy['DEFAULT'] = 0; + MenuPolicy['NEVER'] = 1; + MenuPolicy['ALWAYS'] = 2; })(MenuPolicy || (MenuPolicy = {})); let PreDragStatus; @@ -2648,3 +2648,15 @@ let PreDragStatus; PreDragStatus['PREVIEW_LANDING_FINISHED'] = 5; PreDragStatus['ACTION_CANCELED_BEFORE_DRAG'] = 6; })(PreDragStatus || (PreDragStatus = {})); + +var StyledStringKey; +(function (StyledStringKey) { + StyledStringKey[StyledStringKey["FONT"] = 0] = "FONT"; + StyledStringKey[StyledStringKey["DECORATION"] = 1] = "DECORATION"; + StyledStringKey[StyledStringKey["BASELINE_OFFSET"] = 2] = "BASELINE_OFFSET"; + StyledStringKey[StyledStringKey["LETTER_SPACING"] = 3] = "LETTER_SPACING"; + StyledStringKey[StyledStringKey["TEXT_SHADOW"] = 4] = "TEXT_SHADOW"; + StyledStringKey[StyledStringKey["PARAGRAPH_STYLE"] = 5] = "PARAGRAPH_STYLE"; + StyledStringKey[StyledStringKey["BACKGROUND_COLOR"] = 6] = "BACKGROUND_COLOR"; + StyledStringKey[StyledStringKey["GESTURE"] = 7] = "GESTURE"; +})(StyledStringKey || (StyledStringKey = {})); \ No newline at end of file diff --git a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl.cpp b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl.cpp index 473c799c3a4..7aaaf78a624 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl.cpp +++ b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl.cpp @@ -169,6 +169,8 @@ #include "bridge/declarative_frontend/jsview/menu/js_context_menu.h" #include "bridge/declarative_frontend/jsview/scroll_bar/js_scroll_bar.h" #include "bridge/declarative_frontend/sharedata/js_share_data.h" +#include "bridge/declarative_frontend/style_string/js_span_string.h" +#include "bridge/declarative_frontend/style_string/js_span_object.h" #include "core/components_ng/base/ui_node.h" #include "core/components_ng/base/view_stack_processor.h" #include "core/components_ng/pattern/custom/custom_title_node.h" @@ -499,6 +501,9 @@ static const std::unordered_map> { "ScrollMotion", JSAnimator::JSBind }, { "Animator", JSAnimator::JSBind }, { "Span", JSSpan::JSBind }, + { "SpanString", JSSpanString::JSBind }, + { "MutableSpanString", JSMutableSpanString::JSBind }, + { "FontSpan", JSFontSpan::JSBind }, { "Button", JSButton::JSBind }, { "Canvas", JSCanvas::JSBind }, { "Matrix2D", JSMatrix2d::JSBind }, @@ -572,6 +577,9 @@ static const std::unordered_map> { "ScrollMotion", JSAnimator::JSBind }, { "Animator", JSAnimator::JSBind }, { "Span", JSSpan::JSBind }, + { "SpanString", JSSpanString::JSBind }, + { "MutableSpanString", JSMutableSpanString::JSBind }, + { "FontSpan", JSFontSpan::JSBind }, { "Button", JSButton::JSBind }, { "Canvas", JSCanvas::JSBind }, { "LazyForEach", JSLazyForEach::JSBind }, diff --git a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl_ng.cpp b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl_ng.cpp index f86a3a6c12a..c747a2396ee 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl_ng.cpp +++ b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl_ng.cpp @@ -151,6 +151,8 @@ #include "frameworks/bridge/declarative_frontend/ng/declarative_frontend_ng.h" #include "frameworks/bridge/declarative_frontend/ng/frontend_delegate_declarative_ng.h" #include "frameworks/bridge/declarative_frontend/jsview/js_scrollable_base.h" +#include "frameworks/bridge/declarative_frontend/style_string/js_span_string.h" +#include "frameworks/bridge/declarative_frontend/style_string/js_span_object.h" #ifdef USE_COMPONENTS_LIB #include "frameworks/bridge/js_frontend/engine/jsi/ark_js_value.h" @@ -420,6 +422,9 @@ void JsBindViews(BindingTarget globalObj, void* nativeEngine) JSEnvironment::JSBind(globalObj); JSFlexImpl::JSBind(globalObj); JSSpan::JSBind(globalObj); + JSSpanString::JSBind(globalObj); + JSMutableSpanString::JSBind(globalObj); + JSFontSpan::JSBind(globalObj); JSTabs::JSBind(globalObj); JSTabContent::JSBind(globalObj); JSTabsController::JSBind(globalObj); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_text.cpp b/frameworks/bridge/declarative_frontend/jsview/js_text.cpp index 55678bbb3c9..44ef957e1d7 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_text.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_text.cpp @@ -33,6 +33,7 @@ #include "bridge/declarative_frontend/jsview/js_view_abstract.h" #include "bridge/declarative_frontend/jsview/js_view_common_def.h" #include "bridge/declarative_frontend/jsview/models/text_model_impl.h" +#include "bridge/declarative_frontend/style_string/js_span_string.h" #include "bridge/declarative_frontend/view_stack_processor.h" #include "core/common/container.h" #include "core/components/text/text_theme.h" @@ -512,11 +513,24 @@ void JSText::JsRemoteMessage(const JSCallbackInfo& info) void JSText::Create(const JSCallbackInfo& info) { std::string data; - if (info.Length() > 0) { + if (info.Length() <= 0) { + TextModel::GetInstance()->Create(data); + return; + } + + if (info[0]->IsObject() && JSRef::Cast(info[0])->Unwrap()) { + auto *spanString = JSRef::Cast(info[0])->Unwrap(); + auto spanStringController = spanString->GetController(); + if (spanStringController) { + TextModel::GetInstance()->Create(spanStringController); + } else { + TextModel::GetInstance()->Create(data); + } + } else { ParseJsString(info[0], data); + TextModel::GetInstance()->Create(data); } - TextModel::GetInstance()->Create(data); if (info.Length() <= 1 || !info[1]->IsObject()) { return; } diff --git a/frameworks/bridge/declarative_frontend/jsview/models/text_model_impl.h b/frameworks/bridge/declarative_frontend/jsview/models/text_model_impl.h index 85e6396b15b..db6ecc685f8 100644 --- a/frameworks/bridge/declarative_frontend/jsview/models/text_model_impl.h +++ b/frameworks/bridge/declarative_frontend/jsview/models/text_model_impl.h @@ -26,6 +26,7 @@ namespace OHOS::Ace::Framework { class ACE_EXPORT TextModelImpl : public TextModel { public: void Create(const std::string& content) override; + void Create(const RefPtr& spanString) override {} void SetFont(const Font& value) override; void SetFontSize(const Dimension& value) override; void SetTextColor(const Color& value) override; diff --git a/frameworks/bridge/declarative_frontend/style_string/js_span_object.cpp b/frameworks/bridge/declarative_frontend/style_string/js_span_object.cpp index 31d7a8609a6..6495ed6ef13 100644 --- a/frameworks/bridge/declarative_frontend/style_string/js_span_object.cpp +++ b/frameworks/bridge/declarative_frontend/style_string/js_span_object.cpp @@ -13,11 +13,12 @@ * limitations under the License. */ -#include "frameworks/bridge/declarative_frontend/jsview/js_span_object.h" +#include "frameworks/bridge/declarative_frontend/style_string/js_span_object.h" #include "frameworks/bridge/common/utils/utils.h" #include "frameworks/bridge/declarative_frontend/engine/functions/js_function.h" #include "frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h" + namespace OHOS::Ace::Framework { void JSFontSpan::JSBind(BindingTarget globalObj) @@ -50,7 +51,7 @@ void JSFontSpan::Destructor(JSFontSpan* fontSpan) } } -RefPtr JSFontSpan::ParseJsFontSpan(JSRef obj) +RefPtr JSFontSpan::ParseJsFontSpan(const JSRef& obj) { Font font; Color color; @@ -60,13 +61,14 @@ RefPtr JSFontSpan::ParseJsFontSpan(JSRef obj) } return AceType::MakeRefPtr(font); } + void JSFontSpan::GetFontColor(const JSCallbackInfo& info) { CHECK_NULL_VOID(fontSpan_); if (!fontSpan_->GetFont().fontColor.has_value()) { return; } - auto ret = JSRef::Make(JSVal(ToJSValue(fontSpan_->GetFont().GetFontColor()))); + auto ret = JSRef::Make(JSVal(ToJSValue(fontSpan_->GetFont().fontColor.value().ColorToString()))); info.SetReturnValue(ret); } @@ -76,6 +78,7 @@ RefPtr& JSFontSpan::GetFontSpan() { return fontSpan_; } + void JSFontSpan::SetFontSpan(const RefPtr& fontSpan) { fontSpan_ = fontSpan; diff --git a/frameworks/bridge/declarative_frontend/style_string/js_span_object.h b/frameworks/bridge/declarative_frontend/style_string/js_span_object.h index 4d7d358d4ef..d145b744c4d 100644 --- a/frameworks/bridge/declarative_frontend/style_string/js_span_object.h +++ b/frameworks/bridge/declarative_frontend/style_string/js_span_object.h @@ -16,15 +16,12 @@ #ifndef FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_STYLE_STRING_JS_SPAN_OBJECT_H #define FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_STYLE_STRING_JS_SPAN_OBJECT_H -#include "base/geometry/dimension.h" #include "base/memory/ace_type.h" #include "base/memory/referenced.h" #include "bridge/declarative_frontend/engine/bindings_defines.h" +#include "bridge/declarative_frontend/engine/js_ref_ptr.h" #include "bridge/declarative_frontend/engine/js_types.h" -#include "bridge/declarative_frontend/jsview/js_container_base.h" -#include "core/components_ng/pattern/text/span/span_objects.h" -#include "core/components_ng/pattern/text_field/text_field_model.h" -#include "core/pipeline/pipeline_base.h" +#include "core/components_ng/pattern/text/span/span_object.h" namespace OHOS::Ace::Framework { @@ -37,7 +34,7 @@ public: static void Constructor(const JSCallbackInfo& args); static void Destructor(JSFontSpan* fontSpan); static void JSBind(BindingTarget globalObj); - static RefPtr ParseJsFontSpan(JSRef obj); + static RefPtr ParseJsFontSpan(const JSRef& obj); void GetFontColor(const JSCallbackInfo& info); void SetFontColor(const JSCallbackInfo& info); diff --git a/frameworks/bridge/declarative_frontend/style_string/js_span_string.cpp b/frameworks/bridge/declarative_frontend/style_string/js_span_string.cpp index 4c6001ca782..f7302bb1208 100644 --- a/frameworks/bridge/declarative_frontend/style_string/js_span_string.cpp +++ b/frameworks/bridge/declarative_frontend/style_string/js_span_string.cpp @@ -13,12 +13,12 @@ * limitations under the License. */ -#include "frameworks/bridge/declarative_frontend/jsview/js_span_string.h" +#include "frameworks/bridge/declarative_frontend/style_string/js_span_string.h" #include "frameworks/bridge/common/utils/utils.h" #include "frameworks/bridge/declarative_frontend/engine/functions/js_function.h" -#include "frameworks/bridge/declarative_frontend/jsview/js_span_object.h" #include "frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h" +#include "frameworks/bridge/declarative_frontend/style_string/js_span_object.h" namespace OHOS::Ace::Framework { const std::vector types = { SpanType::Font }; @@ -101,7 +101,9 @@ void JSSpanString::GetSubSpanString(const JSCallbackInfo& info) if (info.Length() == 2 && info[1]->IsNumber()) { length = info[1]->ToNumber(); } - CheckParameters(start, length); + if (!CheckParameters(start, length)) { + return; + } auto spanString = spanString_->GetSubSpanString(start, length); CHECK_NULL_VOID(spanString); JSRef obj = JSClass::NewInstance(); @@ -117,12 +119,22 @@ void JSSpanString::GetSpans(const JSCallbackInfo& info) } auto start = info[0]->ToNumber(); auto length = info[1]->ToNumber(); - CheckParameters(start, length); + if (!CheckParameters(start, length)) { + return; + } std::vector> spans; - if (info.Length() >= 3 && info[2]->IsNumber()) { - CheckSpanType(info[2]->ToNumber()); - SpanType type = static_cast(info[2]->ToNumber()); - spans = spanString_->GetSpans(start, length, type); + if (info.Length() >= 3) { + auto spanTypeObj = info[2]; + if (spanTypeObj->IsNumber()) { + auto spanType = spanTypeObj->ToNumber(); + if (!CheckSpanType(spanType)) { + return; + } + SpanType type = static_cast(spanType); + spans = spanString_->GetSpans(start, length, type); + } else { + JSException::Throw(ERROR_CODE_PARAM_INVALID, "%s", "Input span type check failed."); + } } else { spans = spanString_->GetSpans(start, length); } @@ -140,11 +152,11 @@ JSRef JSSpanString::CreateJSSpanBaseObject(const RefPtr& spa JSRef resultObj = JSRef::New(); resultObj->SetProperty("start", spanObject->GetStartIndex()); resultObj->SetProperty("length", spanObject->GetLength()); - resultObj->SetProperty("styleKey", static_cast(spanObject->GetSpanType())); + resultObj->SetProperty("styledKey", static_cast(spanObject->GetSpanType())); switch (spanObject->GetSpanType()) { case SpanType::Font: { JSRef obj = CreateJsFontSpan(spanObject); - resultObj->SetPropertyObject("styleValue", obj); + resultObj->SetPropertyObject("styledValue", obj); return resultObj; } default: @@ -184,19 +196,23 @@ RefPtr JSSpanString::ParseJsFontSpan(int32_t start, int32_t length, JS return nullptr; } -void JSSpanString::CheckSpanType(const int32_t& type) +bool JSSpanString::CheckSpanType(const int32_t& type) { if (type < 0 || type >= static_cast(types.size())) { JSException::Throw(ERROR_CODE_PARAM_INVALID, "%s", "Input span type check failed."); + return false; } + return true; } -void JSSpanString::CheckParameters(const int32_t& start, const int32_t& length) +bool JSSpanString::CheckParameters(const int32_t& start, const int32_t& length) { // The input parameter must not cross the boundary. if (!spanString_->CheckRange(start, length)) { JSException::Throw(ERROR_CODE_PARAM_INVALID, "%s", "Input parameter check failed."); + return false; } + return true; } std::vector> JSSpanString::ParseJsSpanBaseVector(JSRef obj, int32_t maxLength) @@ -221,24 +237,24 @@ std::vector> JSSpanString::ParseJsSpanBaseVector(JSRefToNumber(); length = length > maxLength - start ? maxLength - start : length; } - auto styleKey = valueObj->GetProperty("styleKey"); + auto styleKey = valueObj->GetProperty("styledKey"); if (styleKey->IsNull() || !styleKey->IsNumber()) { continue; } - auto styleStringValue = valueObj->GetProperty("styleValue"); + auto styleStringValue = valueObj->GetProperty("styledValue"); if (!styleStringValue->IsObject()) { continue; } SpanType type = static_cast(styleKey->ToNumber()); auto spanBase = ParseJsSpanBase(start, length, type, JSRef::Cast(styleStringValue)); if (spanBase) { - spanBaseVector.push_back(spanBase); + spanBaseVector.emplace_back(spanBase); } } return spanBaseVector; } -RefPtr& JSSpanString::GetController() +const RefPtr& JSSpanString::GetController() { return spanString_; } @@ -265,6 +281,7 @@ void JSMutableSpanString::Constructor(const JSCallbackInfo& args) auto spanBases = JSSpanString::ParseJsSpanBaseVector(args[1], StringUtils::ToWstring(data).length()); spanString = AceType::MakeRefPtr(data, spanBases); } + LOGE("jyj string value %s", data.c_str()); jsSpanString->SetController(spanString); jsSpanString->SetMutableController(spanString); args.SetReturnValue(Referenced::RawPtr(jsSpanString)); @@ -297,7 +314,6 @@ void JSMutableSpanString::JSBind(BindingTarget globalObj) JSClass::CustomMethod("replaceStyledString", &JSMutableSpanString::ReplaceSpanString); JSClass::CustomMethod("insertStyledString", &JSMutableSpanString::InsertSpanString); JSClass::CustomMethod("appendStyledString", &JSMutableSpanString::AppendSpanString); - JSClass::Bind(globalObj, JSMutableSpanString::Constructor, JSMutableSpanString::Destructor); } @@ -310,7 +326,9 @@ void JSMutableSpanString::ReplaceString(const JSCallbackInfo& info) int32_t length = info[1]->ToNumber(); auto controller = GetMutableController().Upgrade(); CHECK_NULL_VOID(controller); - CheckParameters(start, length); + if (!CheckParameters(start, length)) { + return; + } std::string data = info[2]->ToString(); controller->ReplaceString(start, length, data); } @@ -342,7 +360,9 @@ void JSMutableSpanString::RemoveString(const JSCallbackInfo& info) auto length = info[1]->ToNumber(); auto controller = GetMutableController().Upgrade(); CHECK_NULL_VOID(controller); - CheckParameters(start, length); + if (!CheckParameters(start, length)) { + return; + } controller->RemoveString(start, length); } @@ -354,20 +374,23 @@ void JSMutableSpanString::ReplaceSpan(const JSCallbackInfo& info) auto paramObject = JSRef::Cast(info[0]); auto startObj = paramObject->GetProperty("start"); auto lengthObj = paramObject->GetProperty("length"); - auto styleKeyObj = paramObject->GetProperty("styleKey"); - auto styleValueObj = paramObject->GetProperty("styleValue"); + auto styleKeyObj = paramObject->GetProperty("styledKey"); + auto styleValueObj = paramObject->GetProperty("styledValue"); if (!startObj->IsNumber() || !lengthObj->IsNumber() || !styleKeyObj->IsNumber() || !styleValueObj->IsObject()) { return; } - CheckSpanType(styleKeyObj->ToNumber()); + auto spanType = styleKeyObj->ToNumber(); + CheckSpanType(spanType); auto start = startObj->ToNumber(); auto length = lengthObj->ToNumber(); - SpanType type = static_cast(styleKeyObj->ToNumber()); + SpanType type = static_cast(spanType); auto spanBase = ParseJsSpanBase(start, length, type, JSRef::Cast(styleValueObj)); CHECK_NULL_VOID(spanBase); auto controller = GetMutableController().Upgrade(); CHECK_NULL_VOID(controller); - CheckParameters(start, length); + if (!CheckParameters(start, length)) { + return; + } controller->ReplaceSpan(start, length, spanBase); } @@ -379,20 +402,25 @@ void JSMutableSpanString::AddSpan(const JSCallbackInfo& info) auto paramObject = JSRef::Cast(info[0]); auto startObj = paramObject->GetProperty("start"); auto lengthObj = paramObject->GetProperty("length"); - auto styleKeyObj = paramObject->GetProperty("styleKey"); - auto styleValueObj = paramObject->GetProperty("styleValue"); + auto styleKeyObj = paramObject->GetProperty("styledKey"); + auto styleValueObj = paramObject->GetProperty("styledValue"); if (!startObj->IsNumber() || !lengthObj->IsNumber() || !styleKeyObj->IsNumber() || !styleValueObj->IsObject()) { return; } - CheckSpanType(styleKeyObj->ToNumber()); + auto spanType = styleKeyObj->ToNumber(); + if (!CheckSpanType(spanType)) { + return; + } auto start = startObj->ToNumber(); auto length = lengthObj->ToNumber(); - SpanType type = static_cast(styleKeyObj->ToNumber()); + SpanType type = static_cast(spanType); auto spanBase = ParseJsSpanBase(start, length, type, JSRef::Cast(styleValueObj)); CHECK_NULL_VOID(spanBase); auto controller = GetMutableController().Upgrade(); CHECK_NULL_VOID(controller); - CheckParameters(start, length); + if (!CheckParameters(start, length)) { + return; + } controller->AddSpan(spanBase); } @@ -403,11 +431,16 @@ void JSMutableSpanString::RemoveSpan(const JSCallbackInfo& info) } auto start = info[0]->ToNumber(); auto length = info[1]->ToNumber(); - CheckSpanType(info[2]->ToNumber()); - SpanType type = static_cast(info[2]->ToNumber()); + auto spanType = info[2]->ToNumber(); + if (!CheckSpanType(spanType)) { + return; + } + SpanType type = static_cast(spanType); auto controller = GetMutableController().Upgrade(); CHECK_NULL_VOID(controller); - CheckParameters(start, length); + if (!CheckParameters(start, length)) { + return; + } controller->RemoveSpan(start, length, type); } @@ -420,7 +453,9 @@ void JSMutableSpanString::RemoveSpans(const JSCallbackInfo& info) CHECK_NULL_VOID(controller); auto start = info[0]->ToNumber(); auto length = info[1]->ToNumber(); - CheckParameters(start, length); + if (!CheckParameters(start, length)) { + return; + } controller->RemoveSpans(start, length); } @@ -444,7 +479,9 @@ void JSMutableSpanString::ReplaceSpanString(const JSCallbackInfo& info) CHECK_NULL_VOID(spanStringController); auto controller = GetMutableController().Upgrade(); CHECK_NULL_VOID(controller); - CheckParameters(start, length); + if (!CheckParameters(start, length)) { + return; + } controller->ReplaceSpanString(start, length, spanStringController); } diff --git a/frameworks/bridge/declarative_frontend/style_string/js_span_string.h b/frameworks/bridge/declarative_frontend/style_string/js_span_string.h index ad2eb8bbde1..40885bbc363 100644 --- a/frameworks/bridge/declarative_frontend/style_string/js_span_string.h +++ b/frameworks/bridge/declarative_frontend/style_string/js_span_string.h @@ -47,10 +47,10 @@ public: static JSRef CreateJsFontSpan(const RefPtr& spanObject); static RefPtr ParseJsSpanBase(int32_t start, int32_t length, SpanType type, JSRef obj); static RefPtr ParseJsFontSpan(int32_t start, int32_t length, JSRef obj); - static void CheckSpanType(const int32_t& type); - void CheckParameters(const int32_t& start, const int32_t& length); + static bool CheckSpanType(const int32_t& type); + bool CheckParameters(const int32_t& start, const int32_t& length); void GetSpans(const JSCallbackInfo& info); - RefPtr& GetController(); + const RefPtr& GetController(); void SetController(const RefPtr& spanString); private: diff --git a/frameworks/core/components_ng/pattern/BUILD.gn b/frameworks/core/components_ng/pattern/BUILD.gn index 8c24f3be4cc..3650945cd88 100644 --- a/frameworks/core/components_ng/pattern/BUILD.gn +++ b/frameworks/core/components_ng/pattern/BUILD.gn @@ -444,6 +444,9 @@ build_component_ng("pattern_ng") { "tabs/tabs_node.cpp", "tabs/tabs_pattern.cpp", "text/image_span_view.cpp", + "text/span/mutable_span_string.cpp", + "text/span/span_object.cpp", + "text/span/span_string.cpp", "text/span_model_ng.cpp", "text/span_node.cpp", "text/symbol_span_model_ng.cpp", diff --git a/frameworks/core/components_ng/pattern/text/span/mutable_span_string.cpp b/frameworks/core/components_ng/pattern/text/span/mutable_span_string.cpp index 98ea5e2ec0a..18881ddddbf 100644 --- a/frameworks/core/components_ng/pattern/text/span/mutable_span_string.cpp +++ b/frameworks/core/components_ng/pattern/text/span/mutable_span_string.cpp @@ -19,10 +19,9 @@ #include "base/memory/referenced.h" #include "base/utils/string_utils.h" -#include "core/components_ng/pattern/text/span/span_objects.h" +#include "core/components_ng/pattern/text/span/span_object.h" #include "core/components_ng/pattern/text/span/span_string.h" - namespace OHOS::Ace { std::wstring MutableSpanString::GetWideStringSubstr(const std::wstring& content, int32_t start, int32_t length) { @@ -55,11 +54,15 @@ void MutableSpanString::RemoveSpan(int32_t start, int32_t length, SpanType key) auto defaultSpan = MutableSpanString::GetDefaultSpan(key); defaultSpan->UpdateStartIndex(start); defaultSpan->UpdateEndIndex(end); - AddSpan(defaultSpan); + ApplyToSpans(defaultSpan, { start, end }, SpanOperation::REMOVE); SplitInterval(spans, { start, end }); SortSpans(spans); MergeIntervals(spans); - spansMap_[key] = spans; + if (spans.empty()) { + spansMap_.erase(key); + } else { + spansMap_[key] = spans; + } } void MutableSpanString::RemoveSpans(int32_t start, int32_t length) @@ -339,7 +342,7 @@ void MutableSpanString::ReplaceSpanString(int32_t start, int32_t length, const R auto span = spanStringSpan->GetSubSpan(spanStringSpan->GetStartIndex() + start, spanStringSpan->GetEndIndex() + start); ApplyToSpans(span, {spanStringSpan->GetStartIndex() + start, - spanStringSpan->GetEndIndex() + start}); + spanStringSpan->GetEndIndex() + start}, SpanOperation::ADD); spans.emplace_back(span); } spansMap_[it->first] = spans; @@ -357,11 +360,11 @@ void MutableSpanString::AppendSpanString(const RefPtr& spanString) ReplaceSpanString(GetLength(), 0, spanString); } -RefPtr MutableSpanString::GetDefaultSpan(SpanType type) const +RefPtr MutableSpanString::GetDefaultSpan(SpanType type) { switch (type) { case SpanType::Font: - return FontSpan::CreateDefaultSpan(); + return MakeRefPtr(); case SpanType::Background: case SpanType::Decoration: case SpanType::Gesture: diff --git a/frameworks/core/components_ng/pattern/text/span/mutable_span_string.h b/frameworks/core/components_ng/pattern/text/span/mutable_span_string.h index f3ce93d960a..7d4d327863b 100644 --- a/frameworks/core/components_ng/pattern/text/span/mutable_span_string.h +++ b/frameworks/core/components_ng/pattern/text/span/mutable_span_string.h @@ -48,7 +48,7 @@ private: void ApplyReplaceStringToSpans(int32_t start, int32_t length, const std::string& other, SpanStringOperation op); void ApplyInsertStringToSpans(int32_t start, const std::string& other); void ApplyReplaceStringToSpanBase(int32_t start, int32_t length, const std::string& other, SpanStringOperation op); - RefPtr GetDefaultSpan(SpanType type) const; + static RefPtr GetDefaultSpan(SpanType type); static std::wstring GetWideStringSubstr(const std::wstring& content, int32_t start); static std::wstring GetWideStringSubstr(const std::wstring& content, int32_t start, int32_t length); void UpdateSpansWithOffset(int32_t start, int32_t offset, SpanStringOperation op); diff --git a/frameworks/core/components_ng/pattern/text/span/span_object.cpp b/frameworks/core/components_ng/pattern/text/span/span_object.cpp index b9dcdf75af4..104c3a8bbbf 100644 --- a/frameworks/core/components_ng/pattern/text/span/span_object.cpp +++ b/frameworks/core/components_ng/pattern/text/span/span_object.cpp @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "core/components_ng/pattern/text/span/span_objects.h" +#include "core/components_ng/pattern/text/span/span_object.h" #include #include @@ -23,6 +23,19 @@ namespace OHOS::Ace { // SpanBase +std::optional> SpanBase::GetIntersectionInterval(std::pair interval) const +{ + // 检查相交情况 + if (end_ <= interval.first || interval.second <= start_) { + return std::nullopt; + } + + // 计算相交区间 + int start = std::max(start_, interval.first); + int end = std::min(end_, interval.second); + return std::make_optional>(std::make_pair(start, end)); +} + int32_t SpanBase::GetStartIndex() const { return start_; @@ -42,8 +55,34 @@ void SpanBase::UpdateEndIndex(int32_t endIndex) end_ = endIndex; } +int32_t SpanBase::GetLength() const +{ + return end_ - start_; +} + // FontSpan -void FontSpan::ApplyToSpanItem(const RefPtr& spanItem) const +FontSpan::FontSpan(Font font) : SpanBase(0, 0), font_(std::move(font)) {} + +FontSpan::FontSpan(Font font, int32_t start, int32_t end) : SpanBase(start, end), font_(std::move(font)) {} + +void FontSpan::ApplyToSpanItem(const RefPtr& spanItem, SpanOperation operation) const +{ + switch (operation) { + case SpanOperation::ADD: + AddSpanStyle(spanItem); + break; + case SpanOperation::REMOVE: + RemoveSpanStyle(spanItem); + } +} + +RefPtr FontSpan::GetSubSpan(int32_t start, int32_t end) +{ + RefPtr spanBase = MakeRefPtr(font_, start, end); + return spanBase; +} + +void FontSpan::AddSpanStyle(const RefPtr& spanItem) const { if (font_.fontColor.has_value()) { spanItem->fontStyle->UpdateTextColor(font_.fontColor.value()); @@ -66,6 +105,37 @@ void FontSpan::ApplyToSpanItem(const RefPtr& spanItem) const } } +void FontSpan::RemoveSpanStyle(const RefPtr& spanItem) +{ + spanItem->fontStyle->ResetTextColor(); + spanItem->fontStyle->ResetFontFamily(); + spanItem->fontStyle->ResetFontSize(); + spanItem->fontStyle->ResetItalicFontStyle(); + spanItem->fontStyle->ResetFontWeight(); +} + +Font FontSpan::GetFont() const +{ + return font_; +} + +SpanType FontSpan::GetSpanType() const +{ + return SpanType::Font; +} + +std::string FontSpan::ToString() const +{ + std::stringstream str; + str << "FontSpan ( start:"; + str << GetStartIndex(); + str << " end:"; + str << GetEndIndex(); + str << "]"; + std::string output = str.str(); + return output; +} + bool FontSpan::IsAttributesEqual(const RefPtr& other) const { auto fontSpan = DynamicCast(other); diff --git a/frameworks/core/components_ng/pattern/text/span/span_object.h b/frameworks/core/components_ng/pattern/text/span/span_object.h index 06ff19348e6..f275db0cdac 100644 --- a/frameworks/core/components_ng/pattern/text/span/span_object.h +++ b/frameworks/core/components_ng/pattern/text/span/span_object.h @@ -22,8 +22,8 @@ #include "base/memory/ace_type.h" #include "base/memory/referenced.h" -#include "core/components_ng/pattern/text_field/text_field_model.h" #include "core/components_ng/pattern/text/span_node.h" +#include "core/components_ng/pattern/text_field/text_field_model.h" namespace OHOS::Ace { @@ -31,6 +31,11 @@ class AttachmentImage {}; enum class SpanType { Font = 0, Decoration, Background, Gesture }; +enum class SpanOperation { + ADD = 0, + REMOVE, +}; + class SpanWatcher : public virtual AceType { DECLARE_ACE_TYPE(SpanWatcher, AceType); @@ -46,15 +51,14 @@ public: virtual bool IsAttributesEqual(const RefPtr& other) const = 0; virtual RefPtr GetSubSpan(int32_t start, int32_t end) = 0; virtual SpanType GetSpanType() const = 0; - virtual void ApplyToSpanItem(const RefPtr& spanItem) const = 0; - virtual RefPtr CreateNewSpanItem() const = 0; + virtual void ApplyToSpanItem(const RefPtr& spanItem, SpanOperation operation) const = 0; int32_t GetStartIndex() const; int32_t GetEndIndex() const; void UpdateStartIndex(int32_t startIndex); void UpdateEndIndex(int32_t endIndex); int32_t GetLength() const; std::optional> GetIntersectionInterval(std::pair interval) const; - virtual std::string ToString() const; + virtual std::string ToString() const = 0; private: int32_t start_ = 0; @@ -64,6 +68,7 @@ private: class FontSpan : public SpanBase { DECLARE_ACE_TYPE(FontSpan, SpanBase); public: + FontSpan() = default; explicit FontSpan(Font font); FontSpan(Font font, int32_t start, int32_t end); Font GetFont() const; @@ -71,11 +76,13 @@ public: bool IsAttributesEqual(const RefPtr& other) const override; SpanType GetSpanType() const override; std::string ToString() const override; - void ApplyToSpanItem(const RefPtr& spanItem) const override; - RefPtr CreateNewSpanItem() const override; + void ApplyToSpanItem(const RefPtr& spanItem, SpanOperation operation) const override; static RefPtr CreateDefaultSpan(); private: + void AddSpanStyle(const RefPtr& spanItem) const; + static void RemoveSpanStyle(const RefPtr& spanItem); + Font font_; }; diff --git a/frameworks/core/components_ng/pattern/text/span/span_string.cpp b/frameworks/core/components_ng/pattern/text/span/span_string.cpp index 465362ab8aa..21bdcc2d4a0 100644 --- a/frameworks/core/components_ng/pattern/text/span/span_string.cpp +++ b/frameworks/core/components_ng/pattern/text/span/span_string.cpp @@ -16,24 +16,31 @@ #include "core/components_ng/pattern/text/span/span_string.h" #include "base/utils/string_utils.h" -#include "bridge/declarative_frontend/engine/js_types.h" #include "core/components/common/properties/color.h" -#include "core/components_ng/pattern/text/span/span_objects.h" namespace OHOS::Ace { +SpanString::SpanString(const std::string& text, std::vector>& spans) : SpanString(text) +{ + BindWithSpans(spans); +} SpanString::SpanString(const std::string& text) : text_(text) { - auto spanItem = GetDefaultSpanItem(text); + auto spanItem = MakeRefPtr(); + spanItem->content = text; + spanItem->interval = { 0, StringUtils::ToWstring(text).length() }; spans_.emplace_back(spanItem); } -SpanString::SpanString(const std::string& text, std::vector>& spans) : SpanString(text) +SpanString::~SpanString() { - BindWithSpans(spans); + spansMap_.clear(); + watchers_.clear(); + spans_.clear(); } -void SpanString::ApplyToSpans(const RefPtr& span, std::pair interval) +void SpanString::ApplyToSpans( + const RefPtr& span, std::pair interval, SpanOperation operation) { for (auto it = spans_.begin(); it != spans_.end(); ++it) { auto intersection = (*it)->GetIntersectionInterval(interval); @@ -43,7 +50,7 @@ void SpanString::ApplyToSpans(const RefPtr& span, std::pairinterval.first; auto oldEnd = (*it)->interval.second; if (oldStart == intersection->first && intersection->second == oldEnd) { - span->ApplyToSpanItem(*it); + span->ApplyToSpanItem(*it, operation); continue; } @@ -56,7 +63,7 @@ void SpanString::ApplyToSpans(const RefPtr& span, std::pairinterval = { intersection->first, intersection->second }; newSpan->content = StringUtils::ToString( wContent.substr(intersection->first - oldStart, intersection->second - intersection->first)); - span->ApplyToSpanItem(newSpan); + span->ApplyToSpanItem(newSpan, operation); auto newSpan2 = (*it)->GetSameStyleSpanItem(); newSpan2->interval = { intersection->second, oldEnd }; @@ -69,7 +76,7 @@ void SpanString::ApplyToSpans(const RefPtr& span, std::pair intersection->second) { (*it)->content = StringUtils::ToString(wContent.substr(0, intersection->second - oldStart)); (*it)->interval = { oldStart, intersection->second }; - span->ApplyToSpanItem(*it); + span->ApplyToSpanItem(*it, operation); newSpan->interval = { intersection->second, oldEnd }; newSpan->content = StringUtils::ToString(wContent.substr(intersection->second - oldStart)); it = spans_.insert(std::next(it), newSpan); @@ -81,7 +88,7 @@ void SpanString::ApplyToSpans(const RefPtr& span, std::pairinterval = { oldStart, intersection->first }; newSpan->interval = { intersection->first, oldEnd }; newSpan->content = StringUtils::ToString(wContent.substr(intersection->first - oldStart)); - span->ApplyToSpanItem(newSpan); + span->ApplyToSpanItem(newSpan, operation); it = spans_.insert(std::next(it), newSpan); } } @@ -163,10 +170,10 @@ void SpanString::AddSpan(const RefPtr& span) auto end = span->GetEndIndex(); if (spansMap_.find(span->GetSpanType()) == spansMap_.end()) { spansMap_[span->GetSpanType()].emplace_back(span); - ApplyToSpans(span, { start, end }); + ApplyToSpans(span, { start, end }, SpanOperation::ADD); return; } - ApplyToSpans(span, { start, end }); + ApplyToSpans(span, { start, end }, SpanOperation::ADD); SplitInterval(spans, { start, end }); spans.emplace_back(span); SortSpans(spans); @@ -199,14 +206,6 @@ RefPtr SpanString::GetDefaultSpanItem(const std::string& text) auto spanItem = MakeRefPtr(); spanItem->content = text; spanItem->interval = { 0, StringUtils::ToWstring(text).length() }; - auto pipelineContext = PipelineContext::GetCurrentContext(); - auto themeStyle = pipelineContext->GetTheme(); - if (themeStyle) { - auto textStyle = themeStyle->GetTextStyle(); - spanItem->fontStyle->UpdateFontSize(textStyle.GetFontSize()); - spanItem->fontStyle->UpdateFontWeight(textStyle.GetFontWeight()); - spanItem->fontStyle->UpdateTextColor(textStyle.GetTextColor()); - } return spanItem; } @@ -244,7 +243,7 @@ RefPtr SpanString::GetSubSpanString(int32_t start, int32_t length) c int32_t end = start + length; RefPtr span = AceType::MakeRefPtr(StringUtils::ToString(StringUtils::ToWstring(text_).substr(start, length))); - std::map>> subMap; + std::unordered_map>> subMap; for (const auto& map : spansMap_) { auto subList = GetSubSpanList(start, length, map.second); if (!subList.empty()) { @@ -288,13 +287,13 @@ std::list> SpanString::GetSubSpanList( if (spanStart == spanEnd) { continue; } - res.push_back(span->GetSubSpan(spanStart, spanEnd)); + res.emplace_back(span->GetSubSpan(spanStart, spanEnd)); } } return res; } -const std::map>>& SpanString::GetSpansMap() const +const std::unordered_map>>& SpanString::GetSpansMap() const { return spansMap_; } @@ -322,7 +321,7 @@ std::vector> SpanString::GetSpans(int32_t start, int32_t length int32_t end = start + length; RefPtr span; while ((span = GetSpan(start, length, spanType)) != nullptr) { - res.push_back(span); + res.emplace_back(span); start = span->GetEndIndex(); length = end - start; } diff --git a/frameworks/core/components_ng/pattern/text/span/span_string.h b/frameworks/core/components_ng/pattern/text/span/span_string.h index 7a7ed81abf8..c7888ac2ae4 100644 --- a/frameworks/core/components_ng/pattern/text/span/span_string.h +++ b/frameworks/core/components_ng/pattern/text/span/span_string.h @@ -22,16 +22,11 @@ #include #include "base/memory/referenced.h" -#include "core/components_ng/pattern/text/span/span_objects.h" +#include "core/components_ng/pattern/text/span/span_object.h" #include "core/components_ng/pattern/text/text_model.h" namespace OHOS::Ace { -enum class SpanOperation { - ADD = 0, - REMOVE, -}; - enum class SpanStringOperation { REPLACE = 0, INSERT, @@ -44,11 +39,12 @@ class ACE_EXPORT SpanString : public SpanStringBase { public: explicit SpanString(const std::string& text); SpanString(const std::string& text, std::vector>& spans); + ~SpanString() override; const std::string& GetString() const; std::wstring GetWideString(); int32_t GetLength() const; void SetString(const std::string& text); - const std::map>>& GetSpansMap() const; + const std::unordered_map>>& GetSpansMap() const; bool IsEqualToSpanString(const RefPtr& other) const; RefPtr GetSubSpanString(int32_t start, int32_t length) const; std::vector> GetSpans(int32_t start, int32_t length) const; @@ -58,7 +54,6 @@ public: void AddSpanWatcher(const WeakPtr& watcher); void NotifySpanWatcher(); const std::list>& GetSpanItems() const; - static RefPtr GetDefaultSpanItem(const std::string& text); void AddSpan(const RefPtr& span); bool CheckRange(int32_t start, int32_t length, bool allowLengthZero = false) const; @@ -69,9 +64,10 @@ protected: void BindWithSpans(std::vector> spans); void MergeIntervals(std::list>& spans); void SplitInterval(std::list>& spans, std::pair interval); - void ApplyToSpans(const RefPtr& spans, std::pair interval); + void ApplyToSpans(const RefPtr& span, std::pair interval, SpanOperation operation); void SortSpans(std::list>& spans); bool CanMerge(const RefPtr& a, const RefPtr& b); + static RefPtr GetDefaultSpanItem(const std::string& text); std::string text_; std::unordered_map>> spansMap_; diff --git a/frameworks/core/components_ng/pattern/text/span_node.cpp b/frameworks/core/components_ng/pattern/text/span_node.cpp index 870af540a06..41f01781252 100644 --- a/frameworks/core/components_ng/pattern/text/span_node.cpp +++ b/frameworks/core/components_ng/pattern/text/span_node.cpp @@ -479,7 +479,7 @@ uint32_t SpanItem::GetSymbolUnicode() void SpanItem::StartDrag(int32_t start, int32_t end) { selectedStart = std::max(0, start); - int contentLen = content.size(); + int32_t contentLen = content.size(); selectedEnd = std::min(contentLen, end); } @@ -551,8 +551,8 @@ std::optional> SpanItem::GetIntersectionInterval(std } // Calculate the intersection interval - int start = std::max(this->interval.first, interval.first); - int end = std::min(this->interval.second, interval.second); + int32_t start = std::max(this->interval.first, interval.first); + int32_t end = std::min(this->interval.second, interval.second); return std::make_optional>(std::make_pair(start, end)); } diff --git a/frameworks/core/components_ng/pattern/text/text_content_modifier.h b/frameworks/core/components_ng/pattern/text/text_content_modifier.h index e23b8517724..c88bb854d60 100644 --- a/frameworks/core/components_ng/pattern/text/text_content_modifier.h +++ b/frameworks/core/components_ng/pattern/text/text_content_modifier.h @@ -56,7 +56,7 @@ public: void SetParagraph(RefPtr paragraph) { - paragraph_ = paragraph; + paragraph_ = std::move(paragraph); } void SetPrintOffset(const OffsetF& paintOffset) diff --git a/frameworks/core/components_ng/pattern/text/text_model.h b/frameworks/core/components_ng/pattern/text/text_model.h index 261a90f168f..a484718c55f 100644 --- a/frameworks/core/components_ng/pattern/text/text_model.h +++ b/frameworks/core/components_ng/pattern/text/text_model.h @@ -51,6 +51,7 @@ public: virtual ~TextModel() = default; virtual void Create(const std::string& content) = 0; + virtual void Create(const RefPtr& spanString) = 0; virtual void SetFont(const Font& value) = 0; virtual void SetFontSize(const Dimension& value) = 0; virtual void SetTextColor(const Color& value) = 0; diff --git a/frameworks/core/components_ng/pattern/text/text_model_ng.cpp b/frameworks/core/components_ng/pattern/text/text_model_ng.cpp index 987c450ec00..abca7a5c56e 100644 --- a/frameworks/core/components_ng/pattern/text/text_model_ng.cpp +++ b/frameworks/core/components_ng/pattern/text/text_model_ng.cpp @@ -22,6 +22,7 @@ #include "core/components_ng/base/frame_node.h" #include "core/components_ng/base/view_abstract.h" #include "core/components_ng/base/view_stack_processor.h" +#include "core/components_ng/pattern/text/span/span_string.h" #include "core/components_ng/pattern/text/text_event_hub.h" #include "core/components_ng/pattern/text/text_pattern.h" #include "core/components_ng/pattern/text_field/text_field_event_hub.h" @@ -55,6 +56,22 @@ void TextModelNG::Create(const std::string& content) textPattern->ClearSelectionMenu(); } +void TextModelNG::Create(const RefPtr& spanBase) +{ + TextModelNG::Create(""); + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto textPattern = frameNode->GetPattern(); + CHECK_NULL_VOID(textPattern); + auto spanString = AceType::DynamicCast(spanBase); + if (spanString) { + spanString->AddSpanWatcher(WeakPtr(textPattern)); + auto spans = spanString->GetSpanItems(); + textPattern->SetSpanItemChildren(spans); + textPattern->SetSpanStringMode(true); + } +} + RefPtr TextModelNG::CreateFrameNode(int32_t nodeId, const std::string& content) { auto frameNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, nodeId, AceType::MakeRefPtr()); diff --git a/frameworks/core/components_ng/pattern/text/text_model_ng.h b/frameworks/core/components_ng/pattern/text/text_model_ng.h index b434e6981d5..13e07a1dd25 100644 --- a/frameworks/core/components_ng/pattern/text/text_model_ng.h +++ b/frameworks/core/components_ng/pattern/text/text_model_ng.h @@ -27,6 +27,7 @@ namespace OHOS::Ace::NG { class ACE_EXPORT TextModelNG : public TextModel { public: void Create(const std::string& content) override; + void Create(const RefPtr& spanString) override; void SetFont(const Font& value) override; void SetFontSize(const Dimension& value) override; void SetTextColor(const Color& value) override; diff --git a/frameworks/core/components_ng/pattern/text/text_pattern.cpp b/frameworks/core/components_ng/pattern/text/text_pattern.cpp index 4ef6d6d082e..7f02e8bda0b 100644 --- a/frameworks/core/components_ng/pattern/text/text_pattern.cpp +++ b/frameworks/core/components_ng/pattern/text/text_pattern.cpp @@ -1912,6 +1912,11 @@ void TextPattern::OnModifyDone() enabled_ = enabledCache; host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); } + if (isSpanStringMode_) { + for (const auto& span : spans_) { + InheritParentProperties(span); + } + } } void TextPattern::ToJsonValue(std::unique_ptr& json) const @@ -2109,7 +2114,14 @@ void TextPattern::InitSpanItem(std::stack nodes) void TextPattern::BeforeCreateLayoutWrapper() { - PreCreateLayoutWrapper(); + if (!isSpanStringMode_) { + PreCreateLayoutWrapper(); + } else { + // mark content dirty + if (contentMod_) { + contentMod_->ContentChange(); + } + } } void TextPattern::CollectSpanNodes(std::stack nodes, bool& isSpanHasClick) @@ -2850,4 +2862,43 @@ ResultObject TextPattern::GetBuilderResultObject(RefPtr uiNode, int32_t } return resultObject; } + +void TextPattern::UpdateSpanItems(const std::list>& spanItems) +{ + spans_ = spanItems; + auto host = GetHost(); + CHECK_NULL_VOID(host); + for (const auto& span : spans_) { + InheritParentProperties(span); + } + host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); +} + +#define INHERIT_TEXT_STYLE(group, name, func) \ + do { \ + if ((textLayoutProp)->Has##name() && spanItem->group->Has##name()) { \ + spanItem->group->func(textLayoutProp->Get##name().value()); \ + } \ + } while (false) + +void TextPattern::InheritParentProperties(const RefPtr& spanItem) +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto textLayoutProp = host->GetLayoutProperty(); + CHECK_NULL_VOID(textLayoutProp); + INHERIT_TEXT_STYLE(fontStyle, FontSize, UpdateFontSize); + INHERIT_TEXT_STYLE(fontStyle, TextColor, UpdateTextColor); + INHERIT_TEXT_STYLE(fontStyle, ItalicFontStyle, UpdateItalicFontStyle); + INHERIT_TEXT_STYLE(fontStyle, FontWeight, UpdateFontWeight); + INHERIT_TEXT_STYLE(fontStyle, FontFamily, UpdateFontFamily); + INHERIT_TEXT_STYLE(fontStyle, TextShadow, UpdateTextShadow); + INHERIT_TEXT_STYLE(fontStyle, TextCase, UpdateTextCase); + INHERIT_TEXT_STYLE(fontStyle, TextDecoration, UpdateTextDecoration); + INHERIT_TEXT_STYLE(fontStyle, TextDecorationColor, UpdateTextDecorationColor); + INHERIT_TEXT_STYLE(fontStyle, TextDecorationStyle, UpdateTextDecorationStyle); + INHERIT_TEXT_STYLE(fontStyle, LetterSpacing, UpdateLetterSpacing); + + INHERIT_TEXT_STYLE(textLineStyle, LineHeight, UpdateLineHeight); +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/text/text_pattern.h b/frameworks/core/components_ng/pattern/text/text_pattern.h index 8070dcf0c56..108ccfb58b1 100644 --- a/frameworks/core/components_ng/pattern/text/text_pattern.h +++ b/frameworks/core/components_ng/pattern/text/text_pattern.h @@ -33,6 +33,7 @@ #include "core/components_ng/pattern/rich_editor/paragraph_manager.h" #include "core/components_ng/pattern/rich_editor/selection_info.h" #include "core/components_ng/pattern/scrollable/scrollable_pattern.h" +#include "core/components_ng/pattern/text/span/span_object.h" #include "core/components_ng/pattern/text/span_node.h" #include "core/components_ng/pattern/text/text_accessibility_property.h" #include "core/components_ng/pattern/text/text_base.h" @@ -57,8 +58,8 @@ struct SpanNodeInfo { RefPtr containerSpanNode; }; // TextPattern is the base class for text render node to perform paint text. -class TextPattern : public virtual Pattern, public TextDragBase, public TextBase { - DECLARE_ACE_TYPE(TextPattern, Pattern, TextDragBase, TextBase); +class TextPattern : public virtual Pattern, public TextDragBase, public TextBase, public SpanWatcher { + DECLARE_ACE_TYPE(TextPattern, Pattern, TextDragBase, TextBase, SpanWatcher); public: TextPattern() = default; @@ -99,10 +100,7 @@ public: { auto host = GetHost(); CHECK_NULL_RETURN(host, false); - if (host->GetTag() == V2::SYMBOL_ETS_TAG) { - return true; - } - return false; + return host->GetTag() == V2::SYMBOL_ETS_TAG; } bool DefaultSupportDrag() override @@ -496,6 +494,21 @@ public: } bool CheckClickedOnSpanOrText(RectF textContentRect, const Offset& localLocation); + // style string + void SetSpanItemChildren(const std::list>& spans) + { + spans_ = spans; + } + void SetSpanStringMode(bool isSpanStringMode) + { + isSpanStringMode_ = isSpanStringMode; + } + bool GetSpanStringMode() const + { + return isSpanStringMode_; + } + void UpdateSpanItems(const std::list>& spanItems) override; + protected: void OnAttachToFrameNode() override; void OnDetachFromFrameNode(FrameNode* node) override; @@ -613,6 +626,7 @@ private: bool IsLineBreakOrEndOfParagraph(int32_t pos) const; void ToJsonValue(std::unique_ptr& json) const override; + void InheritParentProperties(const RefPtr& spanItem); // to check if drag is in progress bool isMeasureBoundary_ = false; @@ -622,6 +636,7 @@ private: bool blockPress_ = false; bool hasClicked_ = false; bool isDoubleClick_ = false; + bool isSpanStringMode_ = false; int32_t clickedSpanPosition_ = -1; TimeStamp lastClickTimeStamp_; diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index e9ba732cd2a..7ec2f4b1722 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -914,6 +914,9 @@ ohos_source_set("ace_components_pattern") { "$ace_root/frameworks/core/components_ng/pattern/tabs/tabs_node.cpp", "$ace_root/frameworks/core/components_ng/pattern/tabs/tabs_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/text/image_span_view.cpp", + "$ace_root/frameworks/core/components_ng/pattern/text/span/mutable_span_string.cpp", + "$ace_root/frameworks/core/components_ng/pattern/text/span/span_object.cpp", + "$ace_root/frameworks/core/components_ng/pattern/text/span/span_string.cpp", "$ace_root/frameworks/core/components_ng/pattern/text/span_model_ng.cpp", "$ace_root/frameworks/core/components_ng/pattern/text/span_node.cpp", "$ace_root/frameworks/core/components_ng/pattern/text/symbol_span_model_ng.cpp", -- Gitee