blob: 216c747b4411db11058c4fc3827bbe21d85b66a5 [file] [log] [blame]
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001// Copyright 2019 Google LLC.
2#ifndef TextLine_DEFINED
3#define TextLine_DEFINED
4
Julia Lavrovaa3552c52019-05-30 16:12:56 -04005#include "include/core/SkCanvas.h"
6#include "include/private/SkTArray.h"
7#include "include/private/SkTHash.h"
8#include "modules/skparagraph/include/DartTypes.h"
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04009#include "modules/skparagraph/include/Metrics.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040010#include "modules/skparagraph/include/TextStyle.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040011#include "modules/skparagraph/src/Run.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040012#include "src/core/SkSpan.h"
13
14namespace skia {
15namespace textlayout {
16
Julia Lavrovaa3552c52019-05-30 16:12:56 -040017class TextLine {
18public:
Julia Lavrova526df262019-08-21 17:49:44 -040019
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
Julia Lavrovaa3552c52019-05-30 16:12:56 -040029 TextLine() = default;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040030 ~TextLine() = default;
31
Julia Lavrova5207f352019-06-21 12:22:32 -040032 TextLine(ParagraphImpl* master,
33 SkVector offset,
34 SkVector advance,
35 BlockRange blocks,
36 TextRange text,
37 TextRange textWithSpaces,
38 ClusterRange clusters,
Julia Lavrovadb9f6692019-08-01 16:02:17 -040039 ClusterRange clustersWithGhosts,
40 SkScalar widthWithSpaces,
Julia Lavrovaf3ed2732019-09-05 14:35:17 -040041 InternalLineMetrics sizes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -040042
Julia Lavrovac2228562019-08-08 16:51:27 -040043 void setMaster(ParagraphImpl* master) { fMaster = master; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040044
Julia Lavrovac2228562019-08-08 16:51:27 -040045 TextRange trimmedText() const { return fTextRange; }
46 TextRange textWithSpaces() const { return fTextWithWhitespacesRange; }
47 ClusterRange clusters() const { return fClusterRange; }
48 ClusterRange clustersWithSpaces() { return fGhostClusterRange; }
49 Run* ellipsis() const { return fEllipsis.get(); }
Julia Lavrovaf3ed2732019-09-05 14:35:17 -040050 InternalLineMetrics sizes() const { return fSizes; }
Julia Lavrovac2228562019-08-08 16:51:27 -040051 bool empty() const { return fTextRange.empty(); }
Julia Lavrova5207f352019-06-21 12:22:32 -040052
Julia Lavrovad3a32c52020-02-03 09:43:52 -050053 SkScalar spacesWidth() { return fWidthWithSpaces - width(); }
Julia Lavrovac2228562019-08-08 16:51:27 -040054 SkScalar height() const { return fAdvance.fY; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040055 SkScalar width() const {
56 return fAdvance.fX + (fEllipsis != nullptr ? fEllipsis->fAdvance.fX : 0);
57 }
Julia Lavrovac2228562019-08-08 16:51:27 -040058 SkScalar shift() const { return fShift; }
Julia Lavrova5207f352019-06-21 12:22:32 -040059 SkVector offset() const;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040060
Julia Lavrovac2228562019-08-08 16:51:27 -040061 SkScalar alphabeticBaseline() const { return fSizes.alphabeticBaseline(); }
62 SkScalar ideographicBaseline() const { return fSizes.ideographicBaseline(); }
63 SkScalar baseline() const { return fSizes.baseline(); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040064
Julia Lavrova526df262019-08-21 17:49:44 -040065 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;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040070
Julia Lavrovaa3552c52019-05-30 16:12:56 -040071
Julia Lavrovac2228562019-08-08 16:51:27 -040072 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;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040074
Julia Lavrovadb9f6692019-08-01 16:02:17 -040075 void format(TextAlign effectiveAlign, SkScalar maxWidth);
Julia Lavrovaa3552c52019-05-30 16:12:56 -040076 void paint(SkCanvas* canvas);
77
78 void createEllipsis(SkScalar maxWidth, const SkString& ellipsis, bool ltr);
79
80 // For testing internal structures
Julia Lavrova526df262019-08-21 17:49:44 -040081 void scanStyles(StyleType style, const RunStyleVisitor& visitor);
Julia Lavrovaa3552c52019-05-30 16:12:56 -040082
Julia Lavrovadb9f6692019-08-01 16:02:17 -040083 TextAlign assumedTextAlign() const;
84
Julia Lavrovaf3ed2732019-09-05 14:35:17 -040085 void setMaxRunMetrics(const InternalLineMetrics& metrics) { fMaxRunMetrics = metrics; }
86 InternalLineMetrics getMaxRunMetrics() const { return fMaxRunMetrics; }
Julia Lavrova916a9042019-08-08 16:51:27 -040087
Julia Lavrova526df262019-08-21 17:49:44 -040088 ClipContext measureTextInsideOneRun(TextRange textRange,
89 const Run* run,
90 SkScalar runOffsetInLine,
91 SkScalar textOffsetInRunInLine,
Julia Lavrovaf3ed2732019-09-05 14:35:17 -040092 bool includeGhostSpaces,
93 bool limitToClusters) const;
94
95 LineMetrics getMetrics() const;
Julia Lavrova526df262019-08-21 17:49:44 -040096
Julia Lavrova9bd83512020-01-15 14:46:35 -050097 SkRect calculateBoundaries();
98
Julia Lavrova89e678d2020-01-28 10:43:31 -050099 SkRect extendHeight(const ClipContext& context) const;
100
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400101private:
Julia Lavrova5207f352019-06-21 12:22:32 -0400102
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400103 Run* shapeEllipsis(const SkString& ellipsis, Run* run);
104 void justify(SkScalar maxWidth);
105
Julia Lavrova526df262019-08-21 17:49:44 -0400106 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;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400110
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400111 void computeDecorationPaint(SkPaint& paint, SkRect clip, const TextStyle& style, SkScalar thickness,
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400112 SkPath& path) const;
113
114 bool contains(const Cluster* cluster) const {
Julia Lavrova5207f352019-06-21 12:22:32 -0400115 return fTextRange.contains(cluster->textRange());
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400116 }
117
Julia Lavrova5207f352019-06-21 12:22:32 -0400118 ParagraphImpl* fMaster;
119 BlockRange fBlockRange;
120 TextRange fTextRange;
121 TextRange fTextWithWhitespacesRange;
122 ClusterRange fClusterRange;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400123 ClusterRange fGhostClusterRange;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400124
Julia Lavrova526df262019-08-21 17:49:44 -0400125 SkTArray<size_t, true> fRunsInVisualOrder;
Julia Lavrova5207f352019-06-21 12:22:32 -0400126 SkVector fAdvance; // Text size
127 SkVector fOffset; // Text position
128 SkScalar fShift; // Left right
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400129 SkScalar fWidthWithSpaces;
Julia Lavrova5207f352019-06-21 12:22:32 -0400130 std::shared_ptr<Run> fEllipsis; // In case the line ends with the ellipsis
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400131 InternalLineMetrics fSizes; // Line metrics as a max of all run metrics and struts
132 InternalLineMetrics fMaxRunMetrics; // No struts - need it for GetRectForRange(max height)
Julia Lavrova5207f352019-06-21 12:22:32 -0400133 bool fHasBackground;
134 bool fHasShadows;
135 bool fHasDecorations;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400136};
137} // namespace textlayout
138} // namespace skia
139
140#endif // TextLine_DEFINED