• 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/TextStyle.h"
10 #include "modules/skparagraph/src/Run.h"
11 #include "src/core/SkSpan.h"
12 
13 namespace skia {
14 namespace textlayout {
15 
16 class TextLine {
17 public:
18     TextLine() = default;
19     ~TextLine() = default;
20 
21     TextLine(ParagraphImpl* master,
22              SkVector offset,
23              SkVector advance,
24              BlockRange blocks,
25              TextRange text,
26              TextRange textWithSpaces,
27              ClusterRange clusters,
28              ClusterRange clustersWithGhosts,
29              SkScalar widthWithSpaces,
30              LineMetrics sizes);
31 
setMaster(ParagraphImpl * master)32     void setMaster(ParagraphImpl* master) { fMaster = master; }
33 
trimmedText()34     TextRange trimmedText() const { return fTextRange; }
textWithSpaces()35     TextRange textWithSpaces() const { return fTextWithWhitespacesRange; }
clusters()36     ClusterRange clusters() const { return fClusterRange; }
clustersWithSpaces()37     ClusterRange clustersWithSpaces() { return fGhostClusterRange; }
ellipsis()38     Run* ellipsis() const { return fEllipsis.get(); }
sizes()39     LineMetrics sizes() const { return fSizes; }
empty()40     bool empty() const { return fTextRange.empty(); }
41 
height()42     SkScalar height() const { return fAdvance.fY; }
width()43     SkScalar width() const {
44         return fAdvance.fX + (fEllipsis != nullptr ? fEllipsis->fAdvance.fX : 0);
45     }
shift()46     SkScalar shift() const { return fShift; }
widthWithSpaces()47     SkScalar widthWithSpaces() const { return fWidthWithSpaces; }
48     SkVector offset() const;
49 
alphabeticBaseline()50     SkScalar alphabeticBaseline() const { return fSizes.alphabeticBaseline(); }
ideographicBaseline()51     SkScalar ideographicBaseline() const { return fSizes.ideographicBaseline(); }
baseline()52     SkScalar baseline() const { return fSizes.baseline(); }
roundingDelta()53     SkScalar roundingDelta() const { return fSizes.delta(); }
54 
55     using StyleVisitor = std::function<SkScalar(TextRange textRange, const TextStyle& style,
56                                                 SkScalar offsetX)>;
57     void iterateThroughStylesInTextOrder(StyleType styleType, const StyleVisitor& visitor) const;
58 
59     SkScalar calculateLeftVisualOffset(TextRange textRange) const;
60 
61     using RunVisitor = std::function<bool(Run* run, size_t pos, size_t size, TextRange text,
62                                           SkRect clip, SkScalar shift, bool clippingNeeded)>;
63     SkScalar iterateThroughRuns(TextRange textRange,
64                                 SkScalar offsetX,
65                                 bool includeGhostWhitespaces,
66                                 const RunVisitor& visitor) const;
67 
68     using ClustersVisitor = std::function<bool(const Cluster* cluster, ClusterIndex index, bool leftToRight, bool ghost)>;
69     void iterateThroughClustersInGlyphsOrder(bool reverse, bool includeGhosts, const ClustersVisitor& visitor) const;
70 
71     void format(TextAlign effectiveAlign, SkScalar maxWidth);
72     void paint(SkCanvas* canvas);
73 
74     void createEllipsis(SkScalar maxWidth, const SkString& ellipsis, bool ltr);
75 
76     // For testing internal structures
77     void scanStyles(StyleType style, const StyleVisitor& visitor);
78     void scanRuns(const RunVisitor& visitor);
79 
80     TextAlign assumedTextAlign() const;
81 
82 private:
83 
84     Run* shapeEllipsis(const SkString& ellipsis, Run* run);
85     void justify(SkScalar maxWidth);
86 
87     SkRect measureTextInsideOneRun(TextRange textRange,
88                                    Run* run,
89                                    size_t& pos,
90                                    size_t& size,
91                                    bool includeGhostSpaces,
92                                    bool& clippingNeeded) const;
93 
94     SkScalar paintText(SkCanvas* canvas, TextRange textRange, const TextStyle& style, SkScalar offsetX) const;
95     SkScalar paintBackground(SkCanvas* canvas, TextRange textRange, const TextStyle& style,
96                              SkScalar offsetX) const;
97     SkScalar paintShadow(SkCanvas* canvas, TextRange textRange, const TextStyle& style,
98                          SkScalar offsetX) const;
99     SkScalar paintDecorations(SkCanvas* canvas, TextRange textRange, const TextStyle& style,
100                               SkScalar offsetX) const;
101 
102     void computeDecorationPaint(SkPaint& paint, SkRect clip, const TextStyle& style,
103                                 SkPath& path) const;
104 
contains(const Cluster * cluster)105     bool contains(const Cluster* cluster) const {
106         return fTextRange.contains(cluster->textRange());
107     }
108 
109     ParagraphImpl* fMaster;
110     BlockRange fBlockRange;
111     TextRange fTextRange;
112     TextRange fTextWithWhitespacesRange;
113     ClusterRange fClusterRange;
114     ClusterRange fGhostClusterRange;
115 
116     SkTArray<size_t, true> fLogical;
117     SkVector fAdvance;                  // Text size
118     SkVector fOffset;                   // Text position
119     SkScalar fShift;                    // Left right
120     SkScalar fWidthWithSpaces;
121     std::shared_ptr<Run> fEllipsis;     // In case the line ends with the ellipsis
122     LineMetrics fSizes;                 // Line metrics as a max of all run metrics
123     bool fHasBackground;
124     bool fHasShadows;
125     bool fHasDecorations;
126 
127     // TODO: use for ellipsis the common cache
128     static SkTHashMap<SkFont, Run> fEllipsisCache;  // All found so far shapes of ellipsis
129 };
130 }  // namespace textlayout
131 }  // namespace skia
132 
133 #endif  // TextLine_DEFINED
134