• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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