1 /* 2 * Copyright (c) 2022 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_TEXT_OVERLAY_TEXT_OVERLAY_MANAGER_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_TEXT_OVERLAY_TEXT_OVERLAY_MANAGER_H 18 19 #ifdef USE_ROSEN_DRAWING 20 #include "core/components_ng/render/drawing_forward.h" 21 #endif 22 #include "core/components/common/layout/constants.h" 23 #include "core/components/common/properties/color.h" 24 #include "frameworks/base/geometry/offset.h" 25 #include "frameworks/base/geometry/rect.h" 26 #include "frameworks/base/memory/ace_type.h" 27 #include "frameworks/core/common/ime/text_editing_value.h" 28 #include "frameworks/core/pipeline/base/overlay_show_option.h" 29 30 #ifndef USE_GRAPHIC_TEXT_GINE 31 namespace txt { 32 class Paragraph; 33 } 34 #else 35 namespace OHOS::Rosen { 36 class Typography; 37 } 38 #endif 39 40 #ifndef USE_ROSEN_DRAWING 41 class SkCanvas; 42 #endif 43 44 namespace OHOS::Ace { 45 46 class RenderNode; 47 class Animator; 48 class StackElement; 49 class PipelineContext; 50 class TextOverlayComponent; 51 class TextOverlayManager; 52 53 enum class CursorPositionType { 54 NONE = 0, 55 END, // end of paragraph 56 BOUNDARY, // boundary of LTR and RTL 57 NORMAL, 58 }; 59 60 enum class DirectionStatus : uint8_t { 61 LEFT_LEFT = 0, // System direction is LTR, text direction is LTR. 62 LEFT_RIGHT, 63 RIGHT_LEFT, 64 RIGHT_RIGHT, 65 }; 66 67 // Describe where caret is and how tall visually. 68 struct CaretMetrics { ResetCaretMetrics69 void Reset() 70 { 71 offset.Reset(); 72 height = 0.0; 73 } 74 75 Offset offset; 76 // When caret is close to different glyphs, the height will be different. 77 double height = 0.0; ToStringCaretMetrics78 std::string ToString() const 79 { 80 std::string result = "Offset: "; 81 result += offset.ToString(); 82 result += ", height: "; 83 result += std::to_string(height); 84 return result; 85 } 86 }; 87 88 class TextOverlayBase : public virtual AceType { 89 DECLARE_ACE_TYPE(TextOverlayBase, AceType); 90 91 public: 92 TextOverlayBase() = default; 93 ~TextOverlayBase() override; 94 SetUpdateHandlePosition(const std::function<void (const OverlayShowOption &)> & updateHandlePosition)95 void SetUpdateHandlePosition(const std::function<void(const OverlayShowOption&)>& updateHandlePosition) 96 { 97 updateHandlePosition_ = updateHandlePosition; 98 } 99 SetUpdateHandleDiameter(const std::function<void (const double &)> & updateHandleDiameter)100 void SetUpdateHandleDiameter(const std::function<void(const double&)>& updateHandleDiameter) 101 { 102 updateHandleDiameter_ = updateHandleDiameter; 103 } 104 SetUpdateHandleDiameterInner(const std::function<void (const double &)> & updateHandleDiameterInner)105 void SetUpdateHandleDiameterInner(const std::function<void(const double&)>& updateHandleDiameterInner) 106 { 107 updateHandleDiameterInner_ = updateHandleDiameterInner; 108 } 109 SetOnClipRectChanged(const std::function<void (const Rect &)> & onClipRectChanged)110 void SetOnClipRectChanged(const std::function<void(const Rect&)>& onClipRectChanged) 111 { 112 onClipRectChanged_ = onClipRectChanged; 113 } 114 IsSelectiveDevice()115 static bool IsSelectiveDevice() 116 { 117 return (SystemProperties::GetDeviceType() != DeviceType::TV && 118 SystemProperties::GetDeviceType() != DeviceType::WATCH); 119 } 120 MarkIsOverlayShowed(bool isOverlayShowed)121 void MarkIsOverlayShowed(bool isOverlayShowed) 122 { 123 isOverlayShowed_ = isOverlayShowed; 124 } 125 IsOverlayShowed()126 bool IsOverlayShowed() const 127 { 128 return isOverlayShowed_; 129 } 130 GetSelectedRect()131 const std::vector<Rect>& GetSelectedRect() const 132 { 133 return selectedRect_; 134 } 135 GetSelectHeight()136 double GetSelectHeight() const 137 { 138 return selectHeight_; 139 } 140 141 void ChangeSelection(int32_t start, int32_t end); 142 void InitAnimation(const WeakPtr<PipelineContext>& pipelineContext); 143 bool GetCaretRect(int32_t extent, Rect& caretRect, double caretHeightOffset = 0.0) const; 144 #ifndef USE_ROSEN_DRAWING 145 void PaintSelection(SkCanvas* canvas, const Offset& globalOffset); 146 #else 147 void PaintSelection(RSCanvas* canvas, const Offset& globalOffset); 148 #endif 149 virtual void InitSelection(const Offset& pos, const Offset& globalOffset); 150 virtual void UpdateStartSelection(int32_t end, const Offset& pos, const Offset& globalOffset); 151 virtual void UpdateEndSelection(int32_t start, const Offset& pos, const Offset& globalOffset); 152 virtual void ShowTextOverlay(const Offset& showOffset) = 0; 153 virtual void RegisterCallbacksToOverlay() = 0; 154 virtual Offset GetHandleOffset(int32_t extend) = 0; 155 virtual std::string GetSelectedContent() const = 0; 156 RefPtr<TextOverlayManager> GetTextOverlayManager(const WeakPtr<PipelineContext>& pipelineContext); 157 bool IsSelectedText(const Offset& pos, const Offset& globalOffset); 158 159 protected: 160 #ifndef USE_GRAPHIC_TEXT_GINE 161 std::shared_ptr<txt::Paragraph> paragraph_; 162 #else 163 std::shared_ptr<Rosen::Typography> paragraph_; 164 #endif 165 CursorPositionType cursorPositionType_ = CursorPositionType::NORMAL; 166 DirectionStatus directionStatus_ = DirectionStatus::LEFT_LEFT; 167 Offset clickOffset_; 168 // For ensuring caret is visible on screen, we take a strategy that move the whole text painting area. 169 // It maybe seems rough, and doesn't support scrolling smoothly. 170 Offset textOffsetForShowCaret_; 171 // An outline for caret. It is used by default when the actual size cannot be retrieved. 172 Rect caretProto_; 173 Rect textOverlayPaintRect_; 174 Color selectedColor_ = Color(0x330a59f7); 175 double selectHeight_ = 0.0; 176 // Default to the start of text (according to RTL/LTR). 177 TextAlign textAlign_ = TextAlign::START; 178 // RTL/LTR is inherit from parent. 179 TextDirection defaultTextDirection_ = TextDirection::INHERIT; 180 TextDirection realTextDirection_ = TextDirection::INHERIT; 181 TextAffinity textAffinity_ = TextAffinity::DOWNSTREAM; 182 TextEditingValue textValue_; 183 std::string textForDisplay_; 184 int32_t cursorPositionForShow_ = 0; 185 double cursorWidth_ = 0.0; // The unit is px. 186 bool isOverlayShowed_ = false; // Whether overlay has showed. 187 RefPtr<Animator> animator_; 188 std::function<void(const OverlayShowOption&)> updateHandlePosition_; 189 std::function<void(const double&)> updateHandleDiameter_; 190 std::function<void(const double&)> updateHandleDiameterInner_; 191 std::function<void(const Rect&)> onClipRectChanged_; 192 RefPtr<TextOverlayComponent> textOverlay_; 193 std::vector<Rect> selectedRect_; 194 195 private: 196 Offset MakeEmptyOffset() const; 197 double GetBoundaryOfParagraph(bool isLeftBoundary) const; 198 bool ComputeOffsetForCaretUpstream(int32_t extent, CaretMetrics& result) const; 199 bool ComputeOffsetForCaretDownstream(int32_t extent, CaretMetrics& result) const; 200 bool ComputeOffsetForCaretCloserToClick(int32_t extent, CaretMetrics& result) const; 201 DirectionStatus GetDirectionStatusOfPosition(int32_t position) const; 202 int32_t GetCursorPositionForClick(const Offset& offset, const Offset& globalOffset); 203 int32_t GetGraphemeClusterLength(int32_t extend, bool isPrefix) const; 204 }; 205 206 class PipelineContext; 207 class TextOverlayManager : public virtual AceType { 208 DECLARE_ACE_TYPE(TextOverlayManager, AceType); 209 210 public: 211 explicit TextOverlayManager(const WeakPtr<PipelineContext>& context); 212 ~TextOverlayManager() override; 213 SetTextOverlayBase(const WeakPtr<TextOverlayBase> & textOverlayBase)214 void SetTextOverlayBase(const WeakPtr<TextOverlayBase>& textOverlayBase) 215 { 216 textOverlayBase_ = textOverlayBase; 217 } 218 GetTextOverlayBase()219 const RefPtr<TextOverlayBase> GetTextOverlayBase() const 220 { 221 auto textOverlayBase = textOverlayBase_.Upgrade(); 222 if (!textOverlayBase) { 223 return nullptr; 224 } 225 return textOverlayBase; 226 } 227 GetTextOverlayRect()228 const std::vector<Rect>& GetTextOverlayRect() const 229 { 230 return textOverlayRect_; 231 } 232 AddTextOverlayRect(const Rect & textOverlayRect)233 void AddTextOverlayRect(const Rect& textOverlayRect) 234 { 235 textOverlayRect_.emplace_back(textOverlayRect); 236 } 237 ClearTextOverlayRect()238 void ClearTextOverlayRect() 239 { 240 textOverlayRect_.clear(); 241 } 242 243 // Coordinate offset is used to calculate the local location of the touch point in the event manager. SetCoordinateOffset(const Offset & coordinateOffset)244 void SetCoordinateOffset(const Offset& coordinateOffset) 245 { 246 coordinateOffset_ = coordinateOffset; 247 } 248 249 // Gets the coordinate offset to calculate the local location of the touch point by manually. GetCoordinateOffset()250 const Offset& GetCoordinateOffset() const 251 { 252 return coordinateOffset_; 253 } 254 255 const RefPtr<RenderNode> GetTargetNode() const; 256 void PopTextOverlay(); 257 void PushTextOverlayToStack( 258 const RefPtr<TextOverlayComponent>& textOverlay, const WeakPtr<PipelineContext>& context); 259 260 void HandleCtrlC() const; 261 262 private: 263 WeakPtr<TextOverlayBase> textOverlayBase_; 264 WeakPtr<StackElement> stackElement_; 265 WeakPtr<PipelineContext> context_; 266 std::vector<Rect> textOverlayRect_; 267 Offset coordinateOffset_; 268 }; 269 270 } // namespace OHOS::Ace 271 272 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_TEXT_OVERLAY_TEXT_OVERLAY_MANAGER_H 273