xref: /aosp_15_r20/external/skia/modules/skparagraph/src/TextLine.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 // Copyright 2019 Google LLC.
2 #ifndef TextLine_DEFINED
3 #define TextLine_DEFINED
4 
5 #include "include/core/SkPoint.h"
6 #include "include/core/SkRect.h"
7 #include "include/core/SkScalar.h"
8 #include "include/private/base/SkTArray.h"
9 #include "modules/skparagraph/include/DartTypes.h"
10 #include "modules/skparagraph/include/Metrics.h"
11 #include "modules/skparagraph/include/ParagraphPainter.h"
12 #include "modules/skparagraph/include/TextStyle.h"
13 #include "modules/skparagraph/src/Run.h"
14 #include "src/base/SkBitmaskEnum.h"
15 
16 #include <stddef.h>
17 #include <functional>
18 #include <memory>
19 #include <vector>
20 
21 class SkString;
22 
23 namespace skia {
24 namespace textlayout {
25 
26 class ParagraphImpl;
27 
28 class TextLine {
29 public:
30 
31     struct ClipContext {
32       const Run* run;
33       size_t pos;
34       size_t size;
35       SkScalar fTextShift; // Shifts the text inside the run so it's placed at the right position
36       SkRect clip;
37       SkScalar fExcludedTrailingSpaces;
38       bool clippingNeeded;
39     };
40 
41     enum TextAdjustment {
42         GlyphCluster = 0x01,    // All text producing glyphs pointing to the same ClusterIndex
43         GlyphemeCluster = 0x02, // base glyph + all attached diacritics
44         Grapheme = 0x04,        // Text adjusted to graphemes
45         GraphemeGluster = 0x05, // GlyphCluster & Grapheme
46     };
47 
48     TextLine() = default;
49     TextLine(const TextLine&) = delete;
50     TextLine& operator=(const TextLine&) = delete;
51     TextLine(TextLine&&) = default;
52     TextLine& operator=(TextLine&&) = default;
53     ~TextLine() = default;
54 
55     TextLine(ParagraphImpl* owner,
56              SkVector offset,
57              SkVector advance,
58              BlockRange blocks,
59              TextRange textExcludingSpaces,
60              TextRange text,
61              TextRange textIncludingNewlines,
62              ClusterRange clusters,
63              ClusterRange clustersWithGhosts,
64              SkScalar widthWithSpaces,
65              InternalLineMetrics sizes);
66 
trimmedText()67     TextRange trimmedText() const { return fTextExcludingSpaces; }
textWithNewlines()68     TextRange textWithNewlines() const { return fTextIncludingNewlines; }
text()69     TextRange text() const { return fText; }
clusters()70     ClusterRange clusters() const { return fClusterRange; }
clustersWithSpaces()71     ClusterRange clustersWithSpaces() const { return fGhostClusterRange; }
ellipsis()72     Run* ellipsis() const { return fEllipsis.get(); }
sizes()73     InternalLineMetrics sizes() const { return fSizes; }
empty()74     bool empty() const { return fTextExcludingSpaces.empty(); }
75 
spacesWidth()76     SkScalar spacesWidth() const { return fWidthWithSpaces - width(); }
height()77     SkScalar height() const { return fAdvance.fY; }
width()78     SkScalar width() const {
79         return fAdvance.fX + (fEllipsis != nullptr ? fEllipsis->fAdvance.fX : 0);
80     }
widthWithoutEllipsis()81     SkScalar widthWithoutEllipsis() const { return fAdvance.fX; }
82     SkVector offset() const;
83 
alphabeticBaseline()84     SkScalar alphabeticBaseline() const { return fSizes.alphabeticBaseline(); }
ideographicBaseline()85     SkScalar ideographicBaseline() const { return fSizes.ideographicBaseline(); }
baseline()86     SkScalar baseline() const { return fSizes.baseline(); }
87 
88     using RunVisitor = std::function<bool(
89             const Run* run, SkScalar runOffset, TextRange textRange, SkScalar* width)>;
90     void iterateThroughVisualRuns(bool includingGhostSpaces, const RunVisitor& runVisitor) const;
91     using RunStyleVisitor = std::function<void(
92             TextRange textRange, const TextStyle& style, const ClipContext& context)>;
93     SkScalar iterateThroughSingleRunByStyles(TextAdjustment textAdjustment,
94                                              const Run* run,
95                                              SkScalar runOffset,
96                                              TextRange textRange,
97                                              StyleType styleType,
98                                              const RunStyleVisitor& visitor) const;
99 
100     using ClustersVisitor = std::function<bool(const Cluster* cluster, ClusterIndex index, bool ghost)>;
101     void iterateThroughClustersInGlyphsOrder(bool reverse,
102                                              bool includeGhosts,
103                                              const ClustersVisitor& visitor) const;
104 
105     void format(TextAlign align, SkScalar maxWidth);
106     void paint(ParagraphPainter* painter, SkScalar x, SkScalar y);
107     void visit(SkScalar x, SkScalar y);
108     void ensureTextBlobCachePopulated();
109 
110     void createEllipsis(SkScalar maxWidth, const SkString& ellipsis, bool ltr);
111 
112     // For testing internal structures
113     void scanStyles(StyleType style, const RunStyleVisitor& visitor);
114 
setMaxRunMetrics(const InternalLineMetrics & metrics)115     void setMaxRunMetrics(const InternalLineMetrics& metrics) { fMaxRunMetrics = metrics; }
getMaxRunMetrics()116     InternalLineMetrics getMaxRunMetrics() const { return fMaxRunMetrics; }
117 
118     bool isFirstLine() const;
119     bool isLastLine() const;
120     void getRectsForRange(TextRange textRange,
121                           RectHeightStyle rectHeightStyle,
122                           RectWidthStyle rectWidthStyle,
123                           std::vector<TextBox>& boxes) const;
124     void getRectsForPlaceholders(std::vector<TextBox>& boxes);
125     PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx);
126 
127     ClipContext measureTextInsideOneRun(TextRange textRange,
128                                         const Run* run,
129                                         SkScalar runOffsetInLine,
130                                         SkScalar textOffsetInRunInLine,
131                                         bool includeGhostSpaces,
132                                         TextAdjustment textAdjustment) const;
133 
134     LineMetrics getMetrics() const;
135 
136     SkRect extendHeight(const ClipContext& context) const;
137 
shiftVertically(SkScalar shift)138     void shiftVertically(SkScalar shift) { fOffset.fY += shift; }
139 
setAscentStyle(LineMetricStyle style)140     void setAscentStyle(LineMetricStyle style) { fAscentStyle = style; }
setDescentStyle(LineMetricStyle style)141     void setDescentStyle(LineMetricStyle style) { fDescentStyle = style; }
142 
143     bool endsWithHardLineBreak() const;
144 
145 private:
146     std::unique_ptr<Run> shapeEllipsis(const SkString& ellipsis, const Cluster* cluster);
147     void justify(SkScalar maxWidth);
148 
149     void buildTextBlob(TextRange textRange, const TextStyle& style, const ClipContext& context);
150     void paintBackground(ParagraphPainter* painter,
151                          SkScalar x,
152                          SkScalar y,
153                          TextRange textRange,
154                          const TextStyle& style,
155                          const ClipContext& context) const;
156     void paintShadow(ParagraphPainter* painter,
157                      SkScalar x,
158                      SkScalar y,
159                      TextRange textRange,
160                      const TextStyle& style,
161                      const ClipContext& context) const;
162     void paintDecorations(ParagraphPainter* painter,
163                           SkScalar x,
164                           SkScalar y,
165                           TextRange textRange,
166                           const TextStyle& style,
167                           const ClipContext& context) const;
168 
169     void shiftCluster(const Cluster* cluster, SkScalar shift, SkScalar prevShift);
170 
171     ParagraphImpl* fOwner;
172     BlockRange fBlockRange;
173     TextRange fTextExcludingSpaces;
174     TextRange fText;
175     TextRange fTextIncludingNewlines;
176     ClusterRange fClusterRange;
177     ClusterRange fGhostClusterRange;
178     // Avoid the malloc/free in the common case of one run per line
179     skia_private::STArray<1, size_t, true> fRunsInVisualOrder;
180     SkVector fAdvance;                  // Text size
181     SkVector fOffset;                   // Text position
182     SkScalar fShift;                    // Let right
183     SkScalar fWidthWithSpaces;
184     std::unique_ptr<Run> fEllipsis;     // In case the line ends with the ellipsis
185     InternalLineMetrics fSizes;                 // Line metrics as a max of all run metrics and struts
186     InternalLineMetrics fMaxRunMetrics;         // No struts - need it for GetRectForRange(max height)
187     bool fHasBackground;
188     bool fHasShadows;
189     bool fHasDecorations;
190 
191     LineMetricStyle fAscentStyle;
192     LineMetricStyle fDescentStyle;
193 
194     struct TextBlobRecord {
195         void paint(ParagraphPainter* painter, SkScalar x, SkScalar y);
196 
197         sk_sp<SkTextBlob> fBlob;
198         SkPoint fOffset = SkPoint::Make(0.0f, 0.0f);
199         ParagraphPainter::SkPaintOrID fPaint;
200         SkRect fBounds = SkRect::MakeEmpty();
201         bool fClippingNeeded = false;
202         SkRect fClipRect = SkRect::MakeEmpty();
203 
204         // Extra fields only used for the (experimental) visitor
205         const Run* fVisitor_Run;
206         size_t     fVisitor_Pos;
207     };
208     bool fTextBlobCachePopulated;
209 public:
210     std::vector<TextBlobRecord> fTextBlobCache;
211 };
212 }  // namespace textlayout
213 }  // namespace skia
214 
215 namespace sknonstd {
216     template <> struct is_bitmask_enum<skia::textlayout::TextLine::TextAdjustment> : std::true_type {};
217 }  // namespace sknonstd
218 
219 #endif  // TextLine_DEFINED
220