• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 Google LLC.
2 #ifndef TextLine_DEFINED
3 #define TextLine_DEFINED
4 
5 #include "include/core/SkCanvas.h"
6 #include "include/private/SkTArray.h"
7 #include "include/private/SkTHash.h"
8 #include "modules/skparagraph/include/DartTypes.h"
9 #include "modules/skparagraph/include/Metrics.h"
10 #include "modules/skparagraph/include/TextStyle.h"
11 #include "modules/skparagraph/src/Run.h"
12 #include "src/core/SkSpan.h"
13 
14 namespace skia {
15 namespace textlayout {
16 
17 class TextLine {
18 public:
19 
20     struct ClipContext {
21       const Run* run;
22       size_t pos;
23       size_t size;
24       SkScalar fTextShift; // Shifts the text inside the run so it's placed at the right position
25       SkRect clip;
26       bool clippingNeeded;
27     };
28 
29     TextLine() = default;
30     ~TextLine() = default;
31 
32     TextLine(ParagraphImpl* master,
33              SkVector offset,
34              SkVector advance,
35              BlockRange blocks,
36              TextRange text,
37              TextRange textWithSpaces,
38              ClusterRange clusters,
39              ClusterRange clustersWithGhosts,
40              SkScalar widthWithSpaces,
41              InternalLineMetrics sizes);
42 
setMaster(ParagraphImpl * master)43     void setMaster(ParagraphImpl* master) { fMaster = master; }
44 
trimmedText()45     TextRange trimmedText() const { return fTextRange; }
textWithSpaces()46     TextRange textWithSpaces() const { return fTextWithWhitespacesRange; }
clusters()47     ClusterRange clusters() const { return fClusterRange; }
clustersWithSpaces()48     ClusterRange clustersWithSpaces() { return fGhostClusterRange; }
ellipsis()49     Run* ellipsis() const { return fEllipsis.get(); }
sizes()50     InternalLineMetrics sizes() const { return fSizes; }
empty()51     bool empty() const { return fTextRange.empty(); }
52 
spacesWidth()53     SkScalar spacesWidth() { return fWidthWithSpaces - width(); }
height()54     SkScalar height() const { return fAdvance.fY; }
width()55     SkScalar width() const {
56         return fAdvance.fX + (fEllipsis != nullptr ? fEllipsis->fAdvance.fX : 0);
57     }
shift()58     SkScalar shift() const { return fShift; }
59     SkVector offset() const;
60 
alphabeticBaseline()61     SkScalar alphabeticBaseline() const { return fSizes.alphabeticBaseline(); }
ideographicBaseline()62     SkScalar ideographicBaseline() const { return fSizes.ideographicBaseline(); }
baseline()63     SkScalar baseline() const { return fSizes.baseline(); }
64 
65     using RunVisitor = std::function<bool(const Run* run, SkScalar runOffset, TextRange textRange, SkScalar* width)>;
66     void iterateThroughVisualRuns(bool includingGhostSpaces, const RunVisitor& runVisitor) const;
67     using RunStyleVisitor = std::function<void(TextRange textRange, const TextStyle& style, const ClipContext& context)>;
68     SkScalar iterateThroughSingleRunByStyles(const Run* run, SkScalar runOffset, TextRange textRange,
69                                          StyleType styleType, const RunStyleVisitor& visitor) const;
70 
71 
72     using ClustersVisitor = std::function<bool(const Cluster* cluster, ClusterIndex index, bool leftToRight, bool ghost)>;
73     void iterateThroughClustersInGlyphsOrder(bool reverse, bool includeGhosts, const ClustersVisitor& visitor) const;
74 
75     void format(TextAlign effectiveAlign, SkScalar maxWidth);
76     void paint(SkCanvas* canvas);
77 
78     void createEllipsis(SkScalar maxWidth, const SkString& ellipsis, bool ltr);
79 
80     // For testing internal structures
81     void scanStyles(StyleType style, const RunStyleVisitor& visitor);
82 
83     TextAlign assumedTextAlign() const;
84 
setMaxRunMetrics(const InternalLineMetrics & metrics)85     void setMaxRunMetrics(const InternalLineMetrics& metrics) { fMaxRunMetrics = metrics; }
getMaxRunMetrics()86     InternalLineMetrics getMaxRunMetrics() const { return fMaxRunMetrics; }
87 
88     ClipContext measureTextInsideOneRun(TextRange textRange,
89                                         const Run* run,
90                                         SkScalar runOffsetInLine,
91                                         SkScalar textOffsetInRunInLine,
92                                         bool includeGhostSpaces,
93                                         bool limitToClusters) const;
94 
95     LineMetrics getMetrics() const;
96 
97     SkRect calculateBoundaries();
98 
99     SkRect extendHeight(const ClipContext& context) const;
100 
101 private:
102 
103     Run* shapeEllipsis(const SkString& ellipsis, Run* run);
104     void justify(SkScalar maxWidth);
105 
106     void paintText(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
107     void paintBackground(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
108     void paintShadow(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
109     void paintDecorations(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
110 
111     void computeDecorationPaint(SkPaint& paint, SkRect clip, const TextStyle& style, SkScalar thickness,
112                                 SkPath& path) const;
113 
contains(const Cluster * cluster)114     bool contains(const Cluster* cluster) const {
115         return fTextRange.contains(cluster->textRange());
116     }
117 
118     ParagraphImpl* fMaster;
119     BlockRange fBlockRange;
120     TextRange fTextRange;
121     TextRange fTextWithWhitespacesRange;
122     ClusterRange fClusterRange;
123     ClusterRange fGhostClusterRange;
124 
125     SkTArray<size_t, true> fRunsInVisualOrder;
126     SkVector fAdvance;                  // Text size
127     SkVector fOffset;                   // Text position
128     SkScalar fShift;                    // Left right
129     SkScalar fWidthWithSpaces;
130     std::shared_ptr<Run> fEllipsis;     // In case the line ends with the ellipsis
131     InternalLineMetrics fSizes;                 // Line metrics as a max of all run metrics and struts
132     InternalLineMetrics fMaxRunMetrics;         // No struts - need it for GetRectForRange(max height)
133     bool fHasBackground;
134     bool fHasShadows;
135     bool fHasDecorations;
136 };
137 }  // namespace textlayout
138 }  // namespace skia
139 
140 #endif  // TextLine_DEFINED
141