blob: 9abd28d22f5e283c6915b8042c7a51c4d67f9c57 [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 Lavrovaa3552c52019-05-30 16:12:56 -040096private:
Julia Lavrova5207f352019-06-21 12:22:32 -040097
Julia Lavrovaa3552c52019-05-30 16:12:56 -040098 Run* shapeEllipsis(const SkString& ellipsis, Run* run);
99 void justify(SkScalar maxWidth);
100
Julia Lavrova526df262019-08-21 17:49:44 -0400101 void paintText(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
102 void paintBackground(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
103 void paintShadow(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
104 void paintDecorations(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400105
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400106 void computeDecorationPaint(SkPaint& paint, SkRect clip, const TextStyle& style, SkScalar thickness,
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400107 SkPath& path) const;
108
109 bool contains(const Cluster* cluster) const {
Julia Lavrova5207f352019-06-21 12:22:32 -0400110 return fTextRange.contains(cluster->textRange());
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400111 }
112
Julia Lavrova5207f352019-06-21 12:22:32 -0400113 ParagraphImpl* fMaster;
114 BlockRange fBlockRange;
115 TextRange fTextRange;
116 TextRange fTextWithWhitespacesRange;
117 ClusterRange fClusterRange;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400118 ClusterRange fGhostClusterRange;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400119
Julia Lavrova526df262019-08-21 17:49:44 -0400120 SkTArray<size_t, true> fRunsInVisualOrder;
Julia Lavrova5207f352019-06-21 12:22:32 -0400121 SkVector fAdvance; // Text size
122 SkVector fOffset; // Text position
123 SkScalar fShift; // Left right
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400124 SkScalar fWidthWithSpaces;
Julia Lavrova5207f352019-06-21 12:22:32 -0400125 std::shared_ptr<Run> fEllipsis; // In case the line ends with the ellipsis
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400126 InternalLineMetrics fSizes; // Line metrics as a max of all run metrics and struts
127 InternalLineMetrics fMaxRunMetrics; // No struts - need it for GetRectForRange(max height)
Julia Lavrova5207f352019-06-21 12:22:32 -0400128 bool fHasBackground;
129 bool fHasShadows;
130 bool fHasDecorations;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400131};
132} // namespace textlayout
133} // namespace skia
134
135#endif // TextLine_DEFINED