• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/SkTArray.h"
9 #include "modules/skparagraph/include/DartTypes.h"
10 #include "modules/skparagraph/include/Metrics.h"
11 #include "modules/skparagraph/include/TextStyle.h"
12 #include "modules/skparagraph/src/Run.h"
13 
14 #include <stddef.h>
15 #include <functional>
16 #include <memory>
17 #include <vector>
18 
19 class SkCanvas;
20 class SkString;
21 
22 namespace skia {
23 namespace textlayout {
24 
25 class ParagraphImpl;
26 
27 class TextLine {
28 public:
29 
30     struct ClipContext {
31       const Run* run;
32       size_t pos;
33       size_t size;
34       SkScalar fTextShift; // Shifts the text inside the run so it's placed at the right position
35       SkRect clip;
36       SkScalar fExcludedTrailingSpaces;
37       bool clippingNeeded;
38     };
39 
40     TextLine() = default;
41     TextLine(const TextLine&) = delete;
42     TextLine& operator=(const TextLine&) = delete;
43     TextLine(TextLine&&) = default;
44     TextLine& operator=(TextLine&&) = default;
45     ~TextLine() = default;
46 
47     TextLine(ParagraphImpl* owner,
48              SkVector offset,
49              SkVector advance,
50              BlockRange blocks,
51              TextRange textExcludingSpaces,
52              TextRange text,
53              TextRange textIncludingNewlines,
54              ClusterRange clusters,
55              ClusterRange clustersWithGhosts,
56              SkScalar widthWithSpaces,
57              InternalLineMetrics sizes);
58 
trimmedText()59     TextRange trimmedText() const { return fTextExcludingSpaces; }
textWithNewlines()60     TextRange textWithNewlines() const { return fTextIncludingNewlines; }
text()61     TextRange text() const { return fText; }
clusters()62     ClusterRange clusters() const { return fClusterRange; }
clustersWithSpaces()63     ClusterRange clustersWithSpaces() { return fGhostClusterRange; }
ellipsis()64     Run* ellipsis() const { return fEllipsis.get(); }
sizes()65     InternalLineMetrics sizes() const { return fSizes; }
empty()66     bool empty() const { return fTextExcludingSpaces.empty(); }
67 
spacesWidth()68     SkScalar spacesWidth() const { return fWidthWithSpaces - width(); }
height()69     SkScalar height() const { return fAdvance.fY; }
width()70     SkScalar width() const {
71         return fAdvance.fX + (fEllipsis != nullptr ? fEllipsis->fAdvance.fX : 0);
72     }
shift()73     SkScalar shift() const { return fShift; }
74     SkVector offset() const;
75 
alphabeticBaseline()76     SkScalar alphabeticBaseline() const { return fSizes.alphabeticBaseline(); }
ideographicBaseline()77     SkScalar ideographicBaseline() const { return fSizes.ideographicBaseline(); }
baseline()78     SkScalar baseline() const { return fSizes.baseline(); }
79 
80     using RunVisitor = std::function<bool(const Run* run, SkScalar runOffset, TextRange textRange, SkScalar* width)>;
81     void iterateThroughVisualRuns(bool includingGhostSpaces, const RunVisitor& runVisitor) const;
82     using RunStyleVisitor = std::function<void(TextRange textRange, const TextStyle& style, const ClipContext& context)>;
83     SkScalar iterateThroughSingleRunByStyles(const Run* run, SkScalar runOffset, TextRange textRange,
84                                          StyleType styleType, const RunStyleVisitor& visitor) const;
85 
86     using ClustersVisitor = std::function<bool(const Cluster* cluster, bool ghost)>;
87     void iterateThroughClustersInGlyphsOrder(bool reverse, bool includeGhosts, const ClustersVisitor& visitor) const;
88 
89     void format(TextAlign align, SkScalar maxWidth);
90     SkRect paint(SkCanvas* canvas, SkScalar x, SkScalar y);
91     void visit(SkScalar x, SkScalar y);
92     void ensureTextBlobCachePopulated();
93 
94     void createEllipsis(SkScalar maxWidth, const SkString& ellipsis, bool ltr);
95 
96     // For testing internal structures
97     void scanStyles(StyleType style, const RunStyleVisitor& visitor);
98 
setMaxRunMetrics(const InternalLineMetrics & metrics)99     void setMaxRunMetrics(const InternalLineMetrics& metrics) { fMaxRunMetrics = metrics; }
getMaxRunMetrics()100     InternalLineMetrics getMaxRunMetrics() const { return fMaxRunMetrics; }
101 
102     bool isFirstLine();
103     bool isLastLine();
104     void getRectsForRange(TextRange textRange, RectHeightStyle rectHeightStyle, RectWidthStyle rectWidthStyle, std::vector<TextBox>& boxes);
105     void getRectsForPlaceholders(std::vector<TextBox>& boxes);
106     PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx);
107 
108     ClipContext measureTextInsideOneRun(TextRange textRange,
109                                         const Run* run,
110                                         SkScalar runOffsetInLine,
111                                         SkScalar textOffsetInRunInLine,
112                                         bool includeGhostSpaces,
113                                         bool limitToGraphemes) const;
114 
115     LineMetrics getMetrics() const;
116 
117     SkRect extendHeight(const ClipContext& context) const;
118 
119     SkScalar metricsWithoutMultiplier(TextHeightBehavior correction);
shiftVertically(SkScalar shift)120     void shiftVertically(SkScalar shift) { fOffset.fY += shift; }
121 
122     bool endsWithHardLineBreak() const;
123 
124 private:
125 
126     std::unique_ptr<Run> shapeEllipsis(const SkString& ellipsis, const Run& run);
127     void justify(SkScalar maxWidth);
128 
129     void buildTextBlob(TextRange textRange, const TextStyle& style, const ClipContext& context);
130     void paintBackground(SkCanvas* canvas, SkScalar x, SkScalar y, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
131     SkRect paintShadow(SkCanvas* canvas, SkScalar x, SkScalar y, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
132     void paintDecorations(SkCanvas* canvas, SkScalar x, SkScalar y, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
133 
134     void shiftCluster(const Cluster* cluster, SkScalar shift, SkScalar prevShift);
135 
136     ParagraphImpl* fOwner;
137     BlockRange fBlockRange;
138     TextRange fTextExcludingSpaces;
139     TextRange fText;
140     TextRange fTextIncludingNewlines;
141     ClusterRange fClusterRange;
142     ClusterRange fGhostClusterRange;
143     // Avoid the malloc/free in the common case of one run per line
144     SkSTArray<1, size_t, true> fRunsInVisualOrder;
145     SkVector fAdvance;                  // Text size
146     SkVector fOffset;                   // Text position
147     SkScalar fShift;                    // Let right
148     SkScalar fWidthWithSpaces;
149     std::unique_ptr<Run> fEllipsis;     // In case the line ends with the ellipsis
150     InternalLineMetrics fSizes;                 // Line metrics as a max of all run metrics and struts
151     InternalLineMetrics fMaxRunMetrics;         // No struts - need it for GetRectForRange(max height)
152     bool fHasBackground;
153     bool fHasShadows;
154     bool fHasDecorations;
155 
156     LineMetricStyle fAscentStyle;
157     LineMetricStyle fDescentStyle;
158 
159     struct TextBlobRecord {
160         void paint(SkCanvas* canvas, SkScalar x, SkScalar y);
161 
162         sk_sp<SkTextBlob> fBlob;
163         SkPoint fOffset = SkPoint::Make(0.0f, 0.0f);
164         SkPaint fPaint;
165         SkRect fBounds = SkRect::MakeEmpty();
166         bool fClippingNeeded = false;
167         SkRect fClipRect = SkRect::MakeEmpty();
168 
169         // Extra fields only used for the (experimental) visitor
170         const Run* fVisitor_Run;
171         size_t     fVisitor_Pos;
172     };
173     bool fTextBlobCachePopulated;
174 public:
175     std::vector<TextBlobRecord> fTextBlobCache;
176 };
177 }  // namespace textlayout
178 }  // namespace skia
179 
180 #endif  // TextLine_DEFINED
181