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