blob: 465ae9ef2ec25c0a531bf52fe026a247301de44b [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 Lavrovac2228562019-08-08 16:51:27 -040053 SkScalar height() const { return fAdvance.fY; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040054 SkScalar width() const {
55 return fAdvance.fX + (fEllipsis != nullptr ? fEllipsis->fAdvance.fX : 0);
56 }
Julia Lavrovac2228562019-08-08 16:51:27 -040057 SkScalar shift() const { return fShift; }
Julia Lavrova5207f352019-06-21 12:22:32 -040058 SkVector offset() const;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040059
Julia Lavrovac2228562019-08-08 16:51:27 -040060 SkScalar alphabeticBaseline() const { return fSizes.alphabeticBaseline(); }
61 SkScalar ideographicBaseline() const { return fSizes.ideographicBaseline(); }
62 SkScalar baseline() const { return fSizes.baseline(); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040063
Julia Lavrova526df262019-08-21 17:49:44 -040064 using RunVisitor = std::function<bool(const Run* run, SkScalar runOffset, TextRange textRange, SkScalar* width)>;
65 void iterateThroughVisualRuns(bool includingGhostSpaces, const RunVisitor& runVisitor) const;
66 using RunStyleVisitor = std::function<void(TextRange textRange, const TextStyle& style, const ClipContext& context)>;
67 SkScalar iterateThroughSingleRunByStyles(const Run* run, SkScalar runOffset, TextRange textRange,
68 StyleType styleType, const RunStyleVisitor& visitor) const;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040069
Julia Lavrovaa3552c52019-05-30 16:12:56 -040070
Julia Lavrovac2228562019-08-08 16:51:27 -040071 using ClustersVisitor = std::function<bool(const Cluster* cluster, ClusterIndex index, bool leftToRight, bool ghost)>;
72 void iterateThroughClustersInGlyphsOrder(bool reverse, bool includeGhosts, const ClustersVisitor& visitor) const;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040073
Julia Lavrovadb9f6692019-08-01 16:02:17 -040074 void format(TextAlign effectiveAlign, SkScalar maxWidth);
Julia Lavrovaa3552c52019-05-30 16:12:56 -040075 void paint(SkCanvas* canvas);
76
77 void createEllipsis(SkScalar maxWidth, const SkString& ellipsis, bool ltr);
78
79 // For testing internal structures
Julia Lavrova526df262019-08-21 17:49:44 -040080 void scanStyles(StyleType style, const RunStyleVisitor& visitor);
Julia Lavrovaa3552c52019-05-30 16:12:56 -040081
Julia Lavrovadb9f6692019-08-01 16:02:17 -040082 TextAlign assumedTextAlign() const;
83
Julia Lavrovaf3ed2732019-09-05 14:35:17 -040084 void setMaxRunMetrics(const InternalLineMetrics& metrics) { fMaxRunMetrics = metrics; }
85 InternalLineMetrics getMaxRunMetrics() const { return fMaxRunMetrics; }
Julia Lavrova916a9042019-08-08 16:51:27 -040086
Julia Lavrova526df262019-08-21 17:49:44 -040087 ClipContext measureTextInsideOneRun(TextRange textRange,
88 const Run* run,
89 SkScalar runOffsetInLine,
90 SkScalar textOffsetInRunInLine,
Julia Lavrovaf3ed2732019-09-05 14:35:17 -040091 bool includeGhostSpaces,
92 bool limitToClusters) const;
93
94 LineMetrics getMetrics() const;
Julia Lavrova526df262019-08-21 17:49:44 -040095
Julia Lavrova9bd83512020-01-15 14:46:35 -050096 SkRect calculateBoundaries();
97
Julia Lavrovaa3552c52019-05-30 16:12:56 -040098private:
Julia Lavrova5207f352019-06-21 12:22:32 -040099
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400100 Run* shapeEllipsis(const SkString& ellipsis, Run* run);
101 void justify(SkScalar maxWidth);
102
Julia Lavrova526df262019-08-21 17:49:44 -0400103 void paintText(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
104 void paintBackground(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
105 void paintShadow(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
106 void paintDecorations(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400107
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400108 void computeDecorationPaint(SkPaint& paint, SkRect clip, const TextStyle& style, SkScalar thickness,
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400109 SkPath& path) const;
110
111 bool contains(const Cluster* cluster) const {
Julia Lavrova5207f352019-06-21 12:22:32 -0400112 return fTextRange.contains(cluster->textRange());
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400113 }
114
Julia Lavrova5207f352019-06-21 12:22:32 -0400115 ParagraphImpl* fMaster;
116 BlockRange fBlockRange;
117 TextRange fTextRange;
118 TextRange fTextWithWhitespacesRange;
119 ClusterRange fClusterRange;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400120 ClusterRange fGhostClusterRange;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400121
Julia Lavrova526df262019-08-21 17:49:44 -0400122 SkTArray<size_t, true> fRunsInVisualOrder;
Julia Lavrova5207f352019-06-21 12:22:32 -0400123 SkVector fAdvance; // Text size
124 SkVector fOffset; // Text position
125 SkScalar fShift; // Left right
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400126 SkScalar fWidthWithSpaces;
Julia Lavrova5207f352019-06-21 12:22:32 -0400127 std::shared_ptr<Run> fEllipsis; // In case the line ends with the ellipsis
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400128 InternalLineMetrics fSizes; // Line metrics as a max of all run metrics and struts
129 InternalLineMetrics fMaxRunMetrics; // No struts - need it for GetRectForRange(max height)
Julia Lavrova5207f352019-06-21 12:22:32 -0400130 bool fHasBackground;
131 bool fHasShadows;
132 bool fHasDecorations;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400133};
134} // namespace textlayout
135} // namespace skia
136
137#endif // TextLine_DEFINED