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 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 class ACE_EXPORT RichEditorLayoutAlgorithm : public MultipleParagraphLayoutAlgorithm { 110 DECLARE_ACE_TYPE(RichEditorLayoutAlgorithm, MultipleParagraphLayoutAlgorithm); 111 112 public: 113 RichEditorLayoutAlgorithm() = delete; 114 RichEditorLayoutAlgorithm(std::list<RefPtr<SpanItem>> spans, RichEditorParagraphManager* paragraphs, 115 std::optional<TextStyle> typingTextStyle, LRUMap<std::uintptr_t, RefPtr<Paragraph>>* paraMapPtr); 116 ~RichEditorLayoutAlgorithm() override = default; 117 GetParentGlobalOffset()118 const OffsetF& GetParentGlobalOffset() const 119 { 120 return parentGlobalOffset_; 121 } 122 std::optional<SizeF> MeasureContent( 123 const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper) override; 124 void Layout(LayoutWrapper* layoutWrapper) override; 125 void Measure(LayoutWrapper* layoutWrapper) override; 126 GetTextRect()127 const RectF& GetTextRect() 128 { 129 return richTextRect_; 130 } 131 132 protected: 133 void HandleEmptyParagraph(RefPtr<Paragraph> paragraph, const std::list<RefPtr<SpanItem>>& spanGroup) override; 134 RefPtr<SpanItem> GetParagraphStyleSpanItem(const std::list<RefPtr<SpanItem>>& spanGroup) override; SetAdaptFontSizeStepToTextStyle(TextStyle & textStyle,const std::optional<Dimension> & adaptFontSizeStep)135 void SetAdaptFontSizeStepToTextStyle( 136 TextStyle& textStyle, const std::optional<Dimension>& adaptFontSizeStep) override {} 137 void AddImageToParagraph(RefPtr<ImageSpanItem>&, const RefPtr<LayoutWrapper>& iterItem, 138 const LayoutConstraintF& layoutConstrain, const RefPtr<Paragraph>& paragraph, int32_t& spanTextLength, 139 const TextStyle& textStyle) override; 140 void AddPlaceHolderToParagraph(RefPtr<PlaceholderSpanItem>& placeholderSpanItem, 141 const RefPtr<LayoutWrapper>& layoutWrapper, const LayoutConstraintF& layoutConstrain, 142 const RefPtr<Paragraph>& paragraph, int32_t& spanTextLength) override; 143 void UpdateParagraphByCustomSpan(RefPtr<CustomSpanItem>& customSpanItem, LayoutWrapper* layoutWrapper, 144 const RefPtr<Paragraph>& paragraph, int32_t& spanTextLength, 145 CustomSpanPlaceholderInfo& customSpanPlaceholder) override; 146 void AddSymbolSpanToParagraph(const RefPtr<SpanItem>& child, int32_t& spanTextLength, 147 const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& paragraph) override; 148 void AddTextSpanToParagraph(const RefPtr<SpanItem>& child, int32_t& spanTextLength, 149 const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& paragraph) override; 150 151 private: 152 OffsetF GetContentOffset(LayoutWrapper* layoutWrapper) override; 153 bool CreateParagraph(const TextStyle& textStyle, std::u16string content, LayoutWrapper* layoutWrapper, 154 double maxWidth = 0.0) override; 155 bool BuildParagraph(TextStyle& textStyle, const RefPtr<TextLayoutProperty>& layoutProperty, 156 const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper); 157 ParagraphStyle GetParagraphStyle( 158 const TextStyle& textStyle, const std::u16string& content, LayoutWrapper* layoutWrapper) const override; 159 float GetShadowOffset(const std::list<RefPtr<SpanItem>>& group) override; 160 void UpdateRichTextRect(const SizeF& textSize, LayoutWrapper* layoutWrapper); 161 RefPtr<RichEditorPattern> GetRichEditorPattern(LayoutWrapper* layoutWrapper); 162 163 bool SetPlaceholder(LayoutWrapper* layoutWrapper); 164 165 void CopySpanStyle(RefPtr<SpanItem> source, RefPtr<SpanItem> target); 166 void AppendNewLineSpan(); 167 std::optional<SizeF> MeasureContentSize(const LayoutConstraintF& constraint, LayoutWrapper* layoutWrapper); 168 std::optional<SizeF> MeasureEmptyContentSize(const LayoutConstraintF& constraint, LayoutWrapper* layoutWrapper); 169 LayoutConstraintF ReMeasureContent( 170 SizeF& textSize, const LayoutConstraintF& constraint, LayoutWrapper* layoutWrapper); 171 void HandleParagraphCache(); 172 void LayoutParagraphs(const std::vector<ParagraphManager::ParagraphInfo>& paragraphInfo, SizeF& maxSize); 173 std::uintptr_t Hash(const std::list<RefPtr<SpanItem>>& spanGroup); 174 RefPtr<Paragraph> GetOrCreateParagraph(const std::list<RefPtr<SpanItem>>& group, 175 const ParagraphStyle& paraStyle, const std::map<int32_t, AISpan>& aiSpanMap) override; 176 std::string SpansToString(); 177 GetSpans()178 const std::list<RefPtr<SpanItem>>& GetSpans() const 179 { 180 return allSpans_; 181 } 182 183 std::list<RefPtr<SpanItem>> allSpans_; 184 RichEditorParagraphManager* pManager_; 185 OffsetF parentGlobalOffset_; 186 RectF richTextRect_; 187 std::optional<TextStyle> typingTextStyle_; 188 LRUMap<std::uintptr_t, RefPtr<Paragraph>>* const paraMapPtr_; 189 ACE_DISALLOW_COPY_AND_MOVE(RichEditorLayoutAlgorithm); 190 }; 191 } // namespace OHOS::Ace::NG 192 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RICH_EDITOR_RICH_EDITOR_LAYOUT_ALGORITHM_H 193