1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RICH_EDITOR_RICH_EDITOR_LAYOUT_ALGORITHM_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RICH_EDITOR_RICH_EDITOR_LAYOUT_ALGORITHM_H 18 19 #include "core/components_ng/pattern/text/multiple_paragraph_layout_algorithm.h" 20 #include "core/components_ng/pattern/text/text_layout_algorithm.h" 21 #include "core/components_ng/pattern/rich_editor/rich_editor_paragraph_manager.h" 22 23 namespace OHOS::Ace::NG { 24 class StyleManager; 25 template<typename KeyType, typename ValueType> 26 class LRUMap { 27 public: 28 using Iterator = typename std::list<std::pair<KeyType, ValueType>>::iterator; 29 LRUMap()30 LRUMap() {} LRUMap(size_t initialCapacity)31 LRUMap(size_t initialCapacity) : capacity(initialCapacity) {} 32 Get(const KeyType & key)33 Iterator Get(const KeyType& key) 34 { 35 auto it = cacheMap.find(key); 36 if (it == cacheMap.end()) { 37 return cacheList.end(); // Return end iterator if not found 38 } 39 40 // Move the accessed item to the front of the list 41 cacheList.splice(cacheList.begin(), cacheList, it->second); 42 43 return it->second; 44 } 45 End()46 Iterator End() 47 { 48 return cacheList.end(); 49 } 50 Size()51 size_t Size() 52 { 53 return cacheMap.size(); 54 } 55 Erase(const KeyType & key)56 void Erase(const KeyType& key) 57 { 58 auto it = cacheMap.find(key); 59 if (it != cacheMap.end()) { 60 cacheList.erase(it->second); 61 cacheMap.erase(it); 62 } 63 } 64 Clear()65 void Clear() 66 { 67 cacheList.clear(); 68 cacheMap.clear(); 69 } 70 Put(const KeyType & key,const ValueType & value)71 void Put(const KeyType& key, const ValueType& value) 72 { 73 auto it = cacheMap.find(key); 74 if (it != cacheMap.end()) { 75 // Update existing item and move to front 76 cacheList.splice(cacheList.begin(), cacheList, it->second); 77 it->second->second = value; 78 } else { 79 // Insert new item 80 if (cacheList.size() >= capacity) { 81 // Remove least recently used item 82 auto last = cacheList.end(); 83 last--; 84 cacheMap.erase(last->first); 85 cacheList.pop_back(); 86 } 87 cacheList.emplace_front(key, value); 88 cacheMap[key] = cacheList.begin(); 89 } 90 } 91 SetCapacity(size_t newCapacity)92 void SetCapacity(size_t newCapacity) 93 { 94 capacity = newCapacity; 95 while (cacheList.size() > capacity) { 96 auto last = cacheList.end(); 97 last--; 98 cacheMap.erase(last->first); 99 cacheList.pop_back(); 100 } 101 } 102 103 private: 104 size_t capacity = SIZE_MAX; 105 std::list<std::pair<KeyType, ValueType>> cacheList; 106 std::unordered_map<KeyType, Iterator> cacheMap; 107 }; 108 109 struct AISpanLayoutInfo { 110 const std::map<int32_t, AISpan>& aiSpanMap; 111 bool needShowAIDetect = false; 112 }; 113 114 class ACE_EXPORT RichEditorLayoutAlgorithm : public MultipleParagraphLayoutAlgorithm { 115 DECLARE_ACE_TYPE(RichEditorLayoutAlgorithm, MultipleParagraphLayoutAlgorithm); 116 117 public: 118 RichEditorLayoutAlgorithm() = delete; 119 RichEditorLayoutAlgorithm(std::list<RefPtr<SpanItem>> spans, RichEditorParagraphManager* paragraphs, 120 LRUMap<uint64_t, RefPtr<Paragraph>>* paraMapPtr, 121 std::unique_ptr<StyleManager>& styleManager, bool needShowPlaceholder, 122 const AISpanLayoutInfo& aiSpanLayoutInfo); 123 ~RichEditorLayoutAlgorithm() override = default; 124 GetParentGlobalOffset()125 const OffsetF& GetParentGlobalOffset() const 126 { 127 return parentGlobalOffset_; 128 } 129 std::optional<SizeF> MeasureContent( 130 const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper) override; 131 void Layout(LayoutWrapper* layoutWrapper) override; 132 void Measure(LayoutWrapper* layoutWrapper) override; 133 GetTextRect()134 const std::optional<RectF>& GetTextRect() 135 { 136 return richTextRect_; 137 } 138 139 protected: 140 void HandleEmptyParagraph(RefPtr<Paragraph> paragraph, const std::list<RefPtr<SpanItem>>& spanGroup) override; 141 RefPtr<SpanItem> GetParagraphStyleSpanItem(const std::list<RefPtr<SpanItem>>& spanGroup) override; SetAdaptFontSizeStepToTextStyle(TextStyle & textStyle,const std::optional<Dimension> & adaptFontSizeStep)142 void SetAdaptFontSizeStepToTextStyle( 143 TextStyle& textStyle, const std::optional<Dimension>& adaptFontSizeStep) override 144 {} 145 void AddImageToParagraph(RefPtr<ImageSpanItem>& imageSpanItem, const RefPtr<LayoutWrapper>& iterItem, 146 const RefPtr<Paragraph>& paragraph, int32_t& spanTextLength) override; 147 void AddPlaceHolderToParagraph(RefPtr<PlaceholderSpanItem>& placeholderSpanItem, 148 const RefPtr<LayoutWrapper>& layoutWrapper, const RefPtr<Paragraph>& paragraph, 149 int32_t& spanTextLength) override; 150 void UpdateParagraphByCustomSpan(RefPtr<CustomSpanItem>& customSpanItem, const RefPtr<Paragraph>& paragraph, 151 int32_t& spanTextLength, CustomSpanPlaceholderInfo& customSpanPlaceholder) override; 152 void AddSymbolSpanToParagraph(const RefPtr<SpanItem>& child, int32_t& spanTextLength, 153 const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& paragraph) override; 154 void AddTextSpanToParagraph(const RefPtr<SpanItem>& child, int32_t& spanTextLength, 155 const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& paragraph) override; 156 ChildrenListWithGuard GetAllChildrenWithBuild(LayoutWrapper* layoutWrapper) override; 157 158 private: 159 void UpdateFrameSizeWithLayoutPolicy(LayoutWrapper* layoutWrapper, SizeF& frameSize); 160 OffsetF GetContentOffset(LayoutWrapper* layoutWrapper) override; 161 bool CreateParagraph(const TextStyle& textStyle, std::u16string content, LayoutWrapper* layoutWrapper, 162 double maxWidth = 0.0) override; 163 bool BuildParagraph(TextStyle& textStyle, const RefPtr<TextLayoutProperty>& layoutProperty, 164 const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper); 165 ParagraphStyle GetEditorParagraphStyle( 166 const TextStyle& textStyle, const std::u16string& content, LayoutWrapper* layoutWrapper) const; 167 float GetShadowOffset(const std::list<RefPtr<SpanItem>>& group) override; 168 void UpdateRichTextRect(const SizeF& textSize, LayoutWrapper* layoutWrapper); 169 RefPtr<RichEditorPattern> GetRichEditorPattern(LayoutWrapper* layoutWrapper); 170 171 bool SetPlaceholder(LayoutWrapper* layoutWrapper); 172 173 void CopySpanStyle(RefPtr<SpanItem> source, RefPtr<SpanItem> target); 174 void AppendNewLineSpan(); 175 std::optional<SizeF> MeasureContentSize(const LayoutConstraintF& constraint, LayoutWrapper* layoutWrapper); 176 std::optional<SizeF> MeasureEmptyContentSize(const LayoutConstraintF& constraint, LayoutWrapper* layoutWrapper); 177 LayoutConstraintF ReMeasureContent( 178 SizeF& textSize, const LayoutConstraintF& constraint, LayoutWrapper* layoutWrapper); 179 void HandleParagraphCache(); 180 void UpdateConstraintByLayoutPolicy( 181 const SizeF& textSize, LayoutConstraintF& constraint, LayoutWrapper* layoutWrapper); 182 void UpdateMaxSizeByLayoutPolicy(const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper, 183 SizeF& maxSize); 184 void ReLayoutParagraphByLayoutPolicy(LayoutWrapper* layoutWrapper, float maxWidth); 185 void ReLayoutParagraphBySpan(LayoutWrapper* layoutWrapper, std::vector<TextStyle>& textStyles, 186 std::list<RefPtr<SpanItem>>& group, bool& needReLayout, bool& needReLayoutParagraph); 187 inline uint64_t Hash(uint64_t hash, const RefPtr<SpanItem>& span); 188 uint64_t Hash(const std::list<RefPtr<SpanItem>>& spanGroup); 189 RefPtr<Paragraph> GetOrCreateParagraph(const std::list<RefPtr<SpanItem>>& group, 190 const ParagraphStyle& paraStyle, const std::map<int32_t, AISpan>& aiSpanMap) override; 191 void HandleAISpan(const std::list<RefPtr<SpanItem>>& spans, const AISpanLayoutInfo& aiSpanLayoutInfo); 192 void HandleAISpan(const std::list<RefPtr<SpanItem>>& spans, const std::map<int32_t, AISpan>& aiSpanMap); 193 void HandleTextSizeWhenEmpty(LayoutWrapper* layoutWrapper, SizeF& textSize); 194 std::string SpansToString(); 195 GetSpans()196 const std::list<RefPtr<SpanItem>>& GetSpans() const 197 { 198 return allSpans_; 199 } 200 201 std::list<RefPtr<SpanItem>> allSpans_; 202 RichEditorParagraphManager* pManager_; 203 OffsetF parentGlobalOffset_; 204 std::optional<RectF> richTextRect_; 205 LRUMap<uint64_t, RefPtr<Paragraph>>* const paraMapPtr_; 206 std::unique_ptr<StyleManager>& styleManager_; 207 bool needShowPlaceholder_ = false; 208 int32_t cacheHitCount_ = 0; 209 std::unordered_set<uint64_t> paragraphKeySet_; 210 ACE_DISALLOW_COPY_AND_MOVE(RichEditorLayoutAlgorithm); 211 }; 212 } // namespace OHOS::Ace::NG 213 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RICH_EDITOR_RICH_EDITOR_LAYOUT_ALGORITHM_H 214