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