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