1 /* 2 * Copyright (c) 2022-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_RENDER_PAPAGRAPH_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_RENDER_PAPAGRAPH_H 18 19 #include "base/geometry/ng/size_t.h" 20 #include "base/image/pixel_map.h" 21 #include "base/memory/ace_type.h" 22 #include "core/components/common/layout/constants.h" 23 #include "core/components/common/properties/alignment.h" 24 #include "core/components/common/properties/text_layout_info.h" 25 #include "core/components/common/properties/text_style.h" 26 #include "core/components_ng/render/drawing_forward.h" 27 #include "core/components_ng/render/font_collection.h" 28 #include "core/components_v2/inspector/utils.h" 29 #include "core/pipeline_ng/pipeline_context.h" 30 31 namespace OHOS::Ace::NG { 32 33 enum RectHeightPolicy { 34 COVER_TEXT, 35 COVER_LINE 36 }; 37 38 class LeadingMarginSize { 39 public: 40 LeadingMarginSize() = default; 41 ~LeadingMarginSize() = default; 42 LeadingMarginSize(Dimension width,Dimension height)43 LeadingMarginSize(Dimension width, Dimension height) 44 { 45 width_ = UnitFilter(width); 46 height_ = UnitFilter(height); 47 } 48 ToString()49 std::string ToString() const 50 { 51 static const int32_t precision = 2; 52 std::stringstream ss; 53 ss << std::fixed << std::setprecision(precision); 54 ss << "width: " << width_.ToString(); 55 ss << " height: " << height_.ToString(); 56 return ss.str(); 57 } 58 59 bool operator==(const LeadingMarginSize& size) const 60 { 61 return NearEqual(width_, size.width_) && NearEqual(height_, size.height_); 62 } 63 Width()64 Dimension Width() const 65 { 66 return width_; 67 } 68 Height()69 Dimension Height() const 70 { 71 return height_; 72 } 73 74 private: UnitFilter(Dimension & value)75 Dimension UnitFilter(Dimension& value) 76 { 77 return value.Unit() == DimensionUnit::PERCENT ? Dimension(0.0) : value; 78 } 79 80 Dimension width_; 81 Dimension height_; 82 }; 83 84 struct LineMetrics { 85 float ascender = 0.0f; 86 float descender = 0.0f; 87 float capHeight = 0.0f; 88 float xHeight = 0.0f; 89 float width = 0.0f; 90 float height = 0.0f; 91 float x = 0.0f; 92 float y = 0.0f; 93 int32_t startIndex = 0; 94 int32_t endIndex = 0; 95 }; 96 97 struct LeadingMargin { 98 LeadingMarginSize size; 99 RefPtr<PixelMap> pixmap; 100 101 bool operator==(const LeadingMargin& other) const 102 { 103 return size == other.size && pixmap == other.pixmap; 104 } 105 IsValidLeadingMargin106 bool IsValid() 107 { 108 return size.Width().IsValid() || size.Height().IsValid(); 109 } 110 ToStringLeadingMargin111 std::string ToString() const 112 { 113 auto jsonValue = JsonUtil::Create(true); 114 JSON_STRING_PUT_STRINGABLE(jsonValue, size); 115 jsonValue->Put("pixmap", 116 pixmap ? ("size=" + std::to_string(pixmap->GetWidth()) + "," + std::to_string(pixmap->GetHeight())).c_str() 117 : "nullptr"); 118 return jsonValue->ToString(); 119 } 120 CheckLeadingMarginLeadingMargin121 bool CheckLeadingMargin(const LeadingMargin& other) const 122 { 123 auto flag = size == other.size; 124 if (pixmap && other.pixmap) { 125 flag &= pixmap->GetRawPixelMapPtr() == other.pixmap->GetRawPixelMapPtr(); 126 } else if (!other.pixmap && !pixmap) { 127 flag &= true; 128 } else { 129 flag &= false; 130 } 131 return flag; 132 } 133 }; 134 135 enum TextHeightBehavior { 136 ALL = 0x0, 137 DISABLE_FIRST_ASCENT = 0x1, 138 DISABLE_LAST_ASCENT = 0x2, 139 DISABLE_ALL = 0x1 | 0x2, 140 }; 141 142 struct ParagraphStyle { 143 TextDirection direction = TextDirection::AUTO; 144 TextAlign align = TextAlign::LEFT; 145 TextVerticalAlign verticalAlign = TextVerticalAlign::BASELINE; 146 uint32_t maxLines = UINT32_MAX; 147 std::string fontLocale; 148 WordBreak wordBreak = WordBreak::NORMAL; 149 EllipsisMode ellipsisMode = EllipsisMode::TAIL; 150 LineBreakStrategy lineBreakStrategy = LineBreakStrategy::GREEDY; 151 TextOverflow textOverflow = TextOverflow::CLIP; 152 std::optional<LeadingMargin> leadingMargin; 153 double fontSize = 14.0; 154 Dimension lineHeight; 155 Dimension indent; 156 bool halfLeading = false; 157 Alignment leadingMarginAlign = Alignment::TOP_CENTER; 158 Dimension paragraphSpacing; 159 bool isEndAddParagraphSpacing = false; 160 int32_t textStyleUid = 0; 161 bool isOnlyBetweenLines = false; 162 bool isFirstParagraphLineSpacing = true; 163 bool optimizeTrailingSpace = false; 164 bool enableAutoSpacing = false; 165 166 bool operator==(const ParagraphStyle others) const 167 { 168 return direction == others.direction && align == others.align && verticalAlign == others.verticalAlign && 169 maxLines == others.maxLines && fontLocale == others.fontLocale && wordBreak == others.wordBreak && 170 ellipsisMode == others.ellipsisMode && textOverflow == others.textOverflow && 171 leadingMargin == others.leadingMargin && fontSize == others.fontSize && 172 halfLeading == others.halfLeading && indent == others.indent && 173 paragraphSpacing == others.paragraphSpacing && isOnlyBetweenLines == others.isOnlyBetweenLines && 174 enableAutoSpacing == others.enableAutoSpacing; 175 } 176 177 bool operator!=(const ParagraphStyle others) const 178 { 179 return !(*this == others); 180 } 181 ToStringParagraphStyle182 std::string ToString() const 183 { 184 std::string result = "TextAlign: "; 185 result += V2::ConvertWrapTextAlignToString(align); 186 result += ", TextVerticalAlign: "; 187 result += V2::ConvertWrapTextVerticalAlignToString(verticalAlign); 188 result += ", maxLines: "; 189 result += std::to_string(maxLines); 190 result += ", wordBreak: "; 191 result += V2::ConvertWrapWordBreakToString(wordBreak); 192 result += ", textOverflow: "; 193 result += V2::ConvertWrapTextOverflowToString(textOverflow); 194 result += ", leadingMargin: "; 195 result += leadingMargin.has_value() ? leadingMargin.value().ToString().c_str() : "nullptr"; 196 result += ", fontSize: "; 197 result += std::to_string(fontSize); 198 result += ", indent: "; 199 result += ", paragraphSpacing: "; 200 result += paragraphSpacing.ToString(); 201 result += indent.ToString(); 202 result += ", enableAutoSpacing: "; 203 result += enableAutoSpacing; 204 return result; 205 } 206 }; 207 208 struct CaretMetricsF { 209 CaretMetricsF() = default; CaretMetricsFCaretMetricsF210 CaretMetricsF(const OffsetF& position, float h) 211 { 212 offset = position; 213 height = h; 214 } ResetCaretMetricsF215 void Reset() 216 { 217 offset.Reset(); 218 height = 0.0; 219 } 220 221 OffsetF offset; 222 // When caret is close to different glyphs, the height will be different. 223 float height = 0.0f; ToStringCaretMetricsF224 std::string ToString() const 225 { 226 std::string result = "Offset: "; 227 result += offset.ToString(); 228 result += ", height: "; 229 result += std::to_string(height); 230 return result; 231 } 232 }; 233 234 struct PositionWithAffinity { PositionWithAffinityPositionWithAffinity235 PositionWithAffinity(size_t pos, TextAffinity affinity) 236 { 237 position_ = pos; 238 affinity_ = affinity; 239 } 240 size_t position_; 241 TextAffinity affinity_; 242 }; 243 244 // Paragraph is interface for drawing text and text paragraph. 245 class Paragraph : public virtual AceType { 246 DECLARE_ACE_TYPE(NG::Paragraph, AceType); 247 248 public: 249 static RefPtr<Paragraph> Create(const ParagraphStyle& paraStyle, const RefPtr<FontCollection>& fontCollection); 250 static RefPtr<Paragraph> CreateRichEditorParagraph( 251 const ParagraphStyle& paraStyle, const RefPtr<FontCollection>& fontCollection); 252 253 static RefPtr<Paragraph> Create(void* paragraph); 254 // whether the paragraph has been build 255 virtual bool IsValid() = 0; 256 257 // interfaces for build text paragraph 258 virtual void PushStyle(const TextStyle& style) = 0; 259 virtual void PopStyle() = 0; 260 virtual void AddText(const std::u16string& text) = 0; 261 virtual void AddSymbol(const std::uint32_t& symbolId) = 0; 262 virtual int32_t AddPlaceholder(const PlaceholderRun& span) = 0; 263 virtual void Build() = 0; 264 virtual void Reset() = 0; 265 266 // interfaces for layout 267 virtual void Layout(float width) = 0; 268 // interfaces for reLayout 269 virtual void ReLayout(float width, const ParagraphStyle& paraStyle, const std::vector<TextStyle>& textStyles) = 0; 270 virtual void ReLayoutForeground(const TextStyle& textStyle) = 0; 271 virtual float GetHeight() = 0; 272 virtual float GetTextWidth() = 0; 273 virtual size_t GetLineCount() = 0; 274 virtual float GetMaxIntrinsicWidth() = 0; 275 virtual bool DidExceedMaxLines() = 0; 276 virtual float GetLongestLine() = 0; 277 virtual float GetLongestLineWithIndent() = 0; 278 virtual float GetMaxWidth() = 0; 279 virtual float GetAlphabeticBaseline() = 0; 280 virtual float GetCharacterWidth(int32_t index) = 0; 281 virtual int32_t GetGlyphIndexByCoordinate(const Offset& offset, bool isSelectionPos = false) = 0; GetGlyphPositionAtCoordinate(const Offset & offset)282 virtual PositionWithAffinity GetGlyphPositionAtCoordinate(const Offset& offset) 283 { 284 PositionWithAffinity finalResult(0, TextAffinity::UPSTREAM); 285 return finalResult; 286 } 287 virtual void GetRectsForRange(int32_t start, int32_t end, std::vector<RectF>& selectedRects) = 0; 288 virtual std::pair<size_t, size_t> GetEllipsisTextRange() = 0; 289 virtual void GetTightRectsForRange(int32_t start, int32_t end, std::vector<RectF>& selectedRects) = 0; 290 virtual void GetRectsForPlaceholders(std::vector<RectF>& selectedRects) = 0; 291 virtual bool ComputeOffsetForCaretDownstream( 292 int32_t extent, CaretMetricsF& result, bool needLineHighest = true) = 0; 293 virtual bool ComputeOffsetForCaretUpstream(int32_t extent, CaretMetricsF& result, bool needLineHighest = true) = 0; 294 virtual bool CalcCaretMetricsByPosition( 295 int32_t extent, CaretMetricsF& caretCaretMetric, TextAffinity textAffinity, bool needLineHighest = true) = 0; 296 virtual bool CalcCaretMetricsByPosition(int32_t extent, CaretMetricsF& caretCaretMetric, 297 const OffsetF& lastTouchOffset, TextAffinity& textAffinity) = 0; 298 virtual void SetIndents(const std::vector<float>& indents) = 0; 299 virtual bool GetWordBoundary(int32_t offset, int32_t& start, int32_t& end) = 0; 300 virtual std::u16string GetParagraphText() = 0; 301 virtual const ParagraphStyle& GetParagraphStyle() const = 0; 302 // interfaces for pass on Symbol Animation interface 303 virtual void SetParagraphSymbolAnimation(const RefPtr<FrameNode>& frameNode) = 0; 304 // interfaces for painting 305 virtual void Paint(RSCanvas& canvas, float x, float y) = 0; 306 #ifndef USE_ROSEN_DRAWING 307 virtual void Paint(SkCanvas* skCanvas, float x, float y) = 0; 308 #endif 309 virtual LineMetrics GetLineMetricsByRectF(RectF& rect) = 0; 310 virtual TextLineMetrics GetLineMetrics(size_t lineNumber) = 0; 311 virtual RectF GetPaintRegion(float x, float y) = 0; 312 virtual bool GetLineMetricsByCoordinate(const Offset& offset, LineMetrics& lineMetrics) = 0; 313 virtual void UpdateColor(size_t from, size_t to, const Color& color) = 0; 314 virtual void TxtGetRectsForRange(int32_t start, int32_t end, 315 RectHeightStyle heightStyle, RectWidthStyle widthStyle, 316 std::vector<RectF>& selectedRects, std::vector<TextDirection>& textDirections) = 0; empty()317 virtual bool empty() const 318 { 319 return false; 320 }; DidExceedMaxLinesInner()321 virtual bool DidExceedMaxLinesInner() 322 { 323 return false; 324 } GetDumpInfo()325 virtual std::string GetDumpInfo() 326 { 327 return ""; 328 } 329 }; 330 } // namespace OHOS::Ace::NG 331 332 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_RENDER_PAPAGRAPH_H 333