From 65baf7b06ef64e9805395c4024a3d2ed45fddd5c Mon Sep 17 00:00:00 2001 From: guanzengkun Date: Wed, 13 Mar 2024 14:16:02 +0800 Subject: [PATCH] =?UTF-8?q?https://gitee.com/openharmony/arkui=5Face=5Feng?= =?UTF-8?q?ine/issues/I985M1=20Description:[=E6=96=B0=E9=9C=80=E6=B1=82]:?= =?UTF-8?q?=20=E6=96=B0=E5=A2=9ESpan=5Fstring.cpp=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=20Sig:=20SIG=5FApplicationFramework=20Feature=20or=20?= =?UTF-8?q?Bugfix:Feature=20Binary=20Source:No=20TDD:(=E8=AF=84=E4=BC=B0?= =?UTF-8?q?=E4=B8=8D=E6=B6=89=E5=8F=8A)=20XTS:Pass=20=E9=A2=84=E6=B5=8B?= =?UTF-8?q?=E8=AF=95:(=E8=AF=84=E4=BC=B0=E4=B8=8D=E6=B6=89=E5=8F=8A)=20Sig?= =?UTF-8?q?ned-off-by:guanzengkun=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pattern/text/span/span_string.cpp | 250 +++++++++++++++++- .../pattern/text/span/span_string.h | 6 +- 2 files changed, 252 insertions(+), 4 deletions(-) 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 a56d2ace830..465362ab8aa 100644 --- a/frameworks/core/components_ng/pattern/text/span/span_string.cpp +++ b/frameworks/core/components_ng/pattern/text/span/span_string.cpp @@ -21,6 +21,18 @@ #include "core/components_ng/pattern/text/span/span_objects.h" namespace OHOS::Ace { + +SpanString::SpanString(const std::string& text) : text_(text) +{ + auto spanItem = GetDefaultSpanItem(text); + spans_.emplace_back(spanItem); +} + +SpanString::SpanString(const std::string& text, std::vector>& spans) : SpanString(text) +{ + BindWithSpans(spans); +} + void SpanString::ApplyToSpans(const RefPtr& span, std::pair interval) { for (auto it = spans_.begin(); it != spans_.end(); ++it) { @@ -40,7 +52,7 @@ void SpanString::ApplyToSpans(const RefPtr& span, std::pairfirst && intersection->second < oldEnd) { (*it)->interval = { oldStart, intersection->first }; (*it)->content = StringUtils::ToString(wContent.substr(0, intersection->first - oldStart)); - + newSpan->interval = { intersection->first, intersection->second }; newSpan->content = StringUtils::ToString( wContent.substr(intersection->first - oldStart, intersection->second - intersection->first)); @@ -161,4 +173,240 @@ void SpanString::AddSpan(const RefPtr& span) MergeIntervals(spans); spansMap_[span->GetSpanType()] = spans; } + +bool SpanString::CheckRange(int32_t start, int32_t length, bool allowLengthZero) const +{ + if (length < 0 || (length == 0 && !allowLengthZero)) { + return false; + } + + auto len = GetLength(); + auto end = start + length; + + if (start > len || end > len) { + return false; + } + + if (start < 0) { + return false; + } + + return true; +} + +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; +} + +void SpanString::SetString(const std::string& text) +{ + text_ = text; +} + +const std::string& SpanString::GetString() const +{ + return text_; +} + +std::wstring SpanString::GetWideString() +{ + return StringUtils::ToWstring(text_); +} + +int32_t SpanString::GetLength() const +{ + return StringUtils::ToWstring(text_).length(); +} + +bool SpanString::IsEqualToSpanString(const RefPtr& other) const +{ + return *this == *other; +} + +RefPtr SpanString::GetSubSpanString(int32_t start, int32_t length) const +{ + if (!CheckRange(start, length)) { + RefPtr span = AceType::MakeRefPtr(""); + return span; + } + int32_t end = start + length; + RefPtr span = + AceType::MakeRefPtr(StringUtils::ToString(StringUtils::ToWstring(text_).substr(start, length))); + std::map>> subMap; + for (const auto& map : spansMap_) { + auto subList = GetSubSpanList(start, length, map.second); + if (!subList.empty()) { + subMap.insert({ map.first, subList }); + } + } + span->spansMap_ = subMap; + + std::list> subSpans_; + for (const auto& spanItem : spans_) { + int32_t spanStart = spanItem->interval.first; + int32_t spanEnd = spanItem->interval.second; + if ((start <= spanStart && spanStart < end) || (start <= spanEnd && spanEnd < end)) { + auto oldStart = spanStart; + auto oldEnd = spanEnd; + spanStart = spanStart <= start ? 0 : spanStart - start; + spanEnd = spanEnd < end ? spanEnd - start : end - start; + auto newSpanItem = spanItem->GetSameStyleSpanItem(); + newSpanItem->interval = { spanStart, spanEnd }; + newSpanItem->content = StringUtils::ToString( + StringUtils::ToWstring(spanItem->content) + .substr(std::max(start - oldStart, 0), std::min(spanEnd, oldEnd) - std::max(start, oldStart))); + subSpans_.emplace_back(newSpanItem); + } + } + span->spans_ = subSpans_; + return span; +} + +std::list> SpanString::GetSubSpanList( + int32_t start, int32_t length, const std::list>& spans) const +{ + std::list> res; + int32_t end = start + length; + for (auto& span : spans) { + int32_t spanStart = span->GetStartIndex(); + int32_t spanEnd = span->GetEndIndex(); + if ((start <= spanStart && spanStart < end) || (start <= spanEnd && spanEnd <= end)) { + spanStart = spanStart <= start ? 0 : spanStart - start; + spanEnd = spanEnd < end ? spanEnd - start : end - start; + if (spanStart == spanEnd) { + continue; + } + res.push_back(span->GetSubSpan(spanStart, spanEnd)); + } + } + return res; +} + +const std::map>>& SpanString::GetSpansMap() const +{ + return spansMap_; +} + +std::vector> SpanString::GetSpans(int32_t start, int32_t length) const +{ + std::vector> res; + if (!CheckRange(start, length)) { + return res; + } + + for (const auto& map : spansMap_) { + auto spans = GetSpans(start, length, map.first); + res.insert(res.begin(), spans.begin(), spans.end()); + } + return res; +} + +std::vector> SpanString::GetSpans(int32_t start, int32_t length, SpanType spanType) const +{ + std::vector> res; + if (!CheckRange(start, length)) { + return res; + } + int32_t end = start + length; + RefPtr span; + while ((span = GetSpan(start, length, spanType)) != nullptr) { + res.push_back(span); + start = span->GetEndIndex(); + length = end - start; + } + return res; +} + +RefPtr SpanString::GetSpan(int32_t start, int32_t length, SpanType spanType) const +{ + if (!CheckRange(start, length) || spansMap_.find(spanType) == spansMap_.end()) { + return nullptr; + } + int32_t end = start + length; + auto spanBaseList = spansMap_.find(spanType)->second; + for (auto itr = spanBaseList.begin(); itr != spanBaseList.end(); ++itr) { + auto spanBase = *itr; + + if ((start <= spanBase->GetStartIndex() && spanBase->GetStartIndex() < end) || + (start <= spanBase->GetEndIndex() && spanBase->GetEndIndex() <= end)) { + int32_t newStart = start <= spanBase->GetStartIndex() ? spanBase->GetStartIndex() : start; + int32_t newEnd = spanBase->GetEndIndex() < end ? spanBase->GetEndIndex() : end; + if (newStart == newEnd) { + continue; + } + return spanBase->GetSubSpan(newStart, newEnd); + } + } + return nullptr; +} + +bool SpanString::operator==(const SpanString& other) const +{ + if (text_ != other.text_ && spansMap_.size() != other.spansMap_.size()) { + return false; + } + for (const auto& map : spansMap_) { + auto spansOtherMap = other.spansMap_.find(map.first); + if (spansOtherMap == other.spansMap_.end()) { + return false; + } + auto spans = map.second; + auto spansOther = spansOtherMap->second; + if (spans.size() != spansOther.size()) { + return false; + } + for (auto spansItr = spans.begin(), spansOtherItr = spansOther.begin(); + spansItr != spans.end() && spansOtherItr != spansOther.end(); ++spansItr, ++spansOtherItr) { + if (!(*spansItr)->IsAttributesEqual(*spansOtherItr) || + (*spansItr)->GetEndIndex() != (*spansOtherItr)->GetEndIndex() || + (*spansItr)->GetStartIndex() != (*spansOtherItr)->GetStartIndex()) { + return false; + } + } + } + return true; +} + +void SpanString::AddSpanWatcher(const WeakPtr& watcher) +{ + watchers_.emplace_back(watcher); +} + +void SpanString::NotifySpanWatcher() +{ + if (spans_.empty()) { + spans_.emplace_back(GetDefaultSpanItem("")); + } + for (const auto& item : watchers_) { + auto watcher = item.Upgrade(); + if (!watcher) { + continue; + } + watcher->UpdateSpanItems(spans_); + } +} + +const std::list>& SpanString::GetSpanItems() const +{ + return spans_; +} + +void SpanString::BindWithSpans(std::vector> spans) +{ + for (auto& span : spans) { + AddSpan(span); + } +} } // namespace OHOS::Ace \ No newline at end of file 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 66ff63787e6..599a8af6a44 100644 --- a/frameworks/core/components_ng/pattern/text/span/span_string.h +++ b/frameworks/core/components_ng/pattern/text/span/span_string.h @@ -31,10 +31,9 @@ class ACE_EXPORT SpanString : public SpanStringBase { DECLARE_ACE_TYPE(SpanString, SpanStringBase); public: - SpanString(const SpanString& other); explicit SpanString(const std::string& text); SpanString(const std::string& text, std::vector>& spans); - std::string GetString() const; + const std::string& GetString() const; std::wstring GetWideString(); int32_t GetLength() const; void SetString(const std::string& text); @@ -45,7 +44,6 @@ public: std::vector> GetSpans(int32_t start, int32_t length, SpanType spanType) const; int32_t GetIndex(const std::string& subString) const; bool operator==(const SpanString& other) const; - SpanString& operator=(const SpanString& other); void AddSpanWatcher(const WeakPtr& watcher); void NotifySpanWatcher(); const std::list>& GetSpanItems() const; @@ -54,6 +52,8 @@ public: protected: RefPtr GetSpan(int32_t start, int32_t length, SpanType spanType) const; + std::list> GetSubSpanList( + int32_t start, int32_t length, const std::list>& spans) const; void BindWithSpans(std::vector> spans); bool CheckRange(int32_t start, int32_t length, bool allowLengthZero = false) const; void MergeIntervals(std::list>& spans); -- Gitee