blob: 113a3943c9f989f75b68605011f1ff92fcb76420 [file] [log] [blame]
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001// Copyright 2019 Google LLC.
2#ifndef TextLine_DEFINED
3#define TextLine_DEFINED
4
Ben Wagner4ca7a812020-05-28 13:48:18 -04005#include "include/core/SkPoint.h"
6#include "include/core/SkRect.h"
7#include "include/core/SkScalar.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04008#include "include/private/SkTArray.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04009#include "modules/skparagraph/include/DartTypes.h"
Julia Lavrovaf3ed2732019-09-05 14:35:17 -040010#include "modules/skparagraph/include/Metrics.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040011#include "modules/skparagraph/include/TextStyle.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040012#include "modules/skparagraph/src/Run.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040013
Ben Wagner4ca7a812020-05-28 13:48:18 -040014#include <stddef.h>
15#include <functional>
Ben Wagner0b13cec2020-05-18 10:52:23 -040016#include <memory>
Ben Wagner4ca7a812020-05-28 13:48:18 -040017#include <vector>
18
19class SkCanvas;
20class SkString;
Ben Wagner0b13cec2020-05-18 10:52:23 -040021
Julia Lavrovaa3552c52019-05-30 16:12:56 -040022namespace skia {
23namespace textlayout {
24
Ben Wagner4ca7a812020-05-28 13:48:18 -040025class ParagraphImpl;
26
Julia Lavrovaa3552c52019-05-30 16:12:56 -040027class TextLine {
28public:
Julia Lavrova526df262019-08-21 17:49:44 -040029
30 struct ClipContext {
31 const Run* run;
32 size_t pos;
33 size_t size;
34 SkScalar fTextShift; // Shifts the text inside the run so it's placed at the right position
35 SkRect clip;
36 bool clippingNeeded;
37 };
38
Julia Lavrovaa3552c52019-05-30 16:12:56 -040039 TextLine() = default;
Ben Wagnerc0872212020-05-27 22:13:55 -040040 TextLine(const TextLine&) = delete;
41 TextLine& operator=(const TextLine&) = delete;
42 TextLine(TextLine&&) = default;
43 TextLine& operator=(TextLine&&) = default;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040044 ~TextLine() = default;
45
Julia Lavrova2aa72452020-08-03 15:18:41 -040046 TextLine(ParagraphImpl* owner,
Julia Lavrova5207f352019-06-21 12:22:32 -040047 SkVector offset,
48 SkVector advance,
49 BlockRange blocks,
50 TextRange text,
51 TextRange textWithSpaces,
52 ClusterRange clusters,
Julia Lavrovadb9f6692019-08-01 16:02:17 -040053 ClusterRange clustersWithGhosts,
54 SkScalar widthWithSpaces,
Julia Lavrovaf3ed2732019-09-05 14:35:17 -040055 InternalLineMetrics sizes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -040056
Julia Lavrovac2228562019-08-08 16:51:27 -040057 TextRange trimmedText() const { return fTextRange; }
58 TextRange textWithSpaces() const { return fTextWithWhitespacesRange; }
59 ClusterRange clusters() const { return fClusterRange; }
60 ClusterRange clustersWithSpaces() { return fGhostClusterRange; }
61 Run* ellipsis() const { return fEllipsis.get(); }
Julia Lavrovaf3ed2732019-09-05 14:35:17 -040062 InternalLineMetrics sizes() const { return fSizes; }
Julia Lavrovac2228562019-08-08 16:51:27 -040063 bool empty() const { return fTextRange.empty(); }
Julia Lavrova5207f352019-06-21 12:22:32 -040064
Julia Lavrovad3a32c52020-02-03 09:43:52 -050065 SkScalar spacesWidth() { return fWidthWithSpaces - width(); }
Julia Lavrovac2228562019-08-08 16:51:27 -040066 SkScalar height() const { return fAdvance.fY; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040067 SkScalar width() const {
68 return fAdvance.fX + (fEllipsis != nullptr ? fEllipsis->fAdvance.fX : 0);
69 }
Julia Lavrovac2228562019-08-08 16:51:27 -040070 SkScalar shift() const { return fShift; }
Julia Lavrova5207f352019-06-21 12:22:32 -040071 SkVector offset() const;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040072
Julia Lavrovac2228562019-08-08 16:51:27 -040073 SkScalar alphabeticBaseline() const { return fSizes.alphabeticBaseline(); }
74 SkScalar ideographicBaseline() const { return fSizes.ideographicBaseline(); }
75 SkScalar baseline() const { return fSizes.baseline(); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040076
Julia Lavrova526df262019-08-21 17:49:44 -040077 using RunVisitor = std::function<bool(const Run* run, SkScalar runOffset, TextRange textRange, SkScalar* width)>;
78 void iterateThroughVisualRuns(bool includingGhostSpaces, const RunVisitor& runVisitor) const;
79 using RunStyleVisitor = std::function<void(TextRange textRange, const TextStyle& style, const ClipContext& context)>;
80 SkScalar iterateThroughSingleRunByStyles(const Run* run, SkScalar runOffset, TextRange textRange,
81 StyleType styleType, const RunStyleVisitor& visitor) const;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040082
Julia Lavrovaf4cf8932020-04-22 14:33:20 -040083 using ClustersVisitor = std::function<bool(const Cluster* cluster, bool ghost)>;
Julia Lavrovac2228562019-08-08 16:51:27 -040084 void iterateThroughClustersInGlyphsOrder(bool reverse, bool includeGhosts, const ClustersVisitor& visitor) const;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040085
Julia Lavrova6bdbd3d2020-05-06 12:03:17 -040086 void format(TextAlign align, SkScalar maxWidth);
Julia Lavrovab6030fb2020-09-08 11:01:49 -040087 SkRect paint(SkCanvas* canvas, SkScalar x, SkScalar y);
Julia Lavrovaa3552c52019-05-30 16:12:56 -040088
89 void createEllipsis(SkScalar maxWidth, const SkString& ellipsis, bool ltr);
90
91 // For testing internal structures
Julia Lavrova526df262019-08-21 17:49:44 -040092 void scanStyles(StyleType style, const RunStyleVisitor& visitor);
Julia Lavrovaa3552c52019-05-30 16:12:56 -040093
Julia Lavrovaf3ed2732019-09-05 14:35:17 -040094 void setMaxRunMetrics(const InternalLineMetrics& metrics) { fMaxRunMetrics = metrics; }
95 InternalLineMetrics getMaxRunMetrics() const { return fMaxRunMetrics; }
Julia Lavrova916a9042019-08-08 16:51:27 -040096
Julia Lavrova8335ab62020-04-27 15:49:53 -040097 bool isFirstLine();
98 bool isLastLine();
99 void getRectsForRange(TextRange textRange, RectHeightStyle rectHeightStyle, RectWidthStyle rectWidthStyle, std::vector<TextBox>& boxes);
100 void getRectsForPlaceholders(std::vector<TextBox>& boxes);
101 PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx);
102
Julia Lavrova526df262019-08-21 17:49:44 -0400103 ClipContext measureTextInsideOneRun(TextRange textRange,
104 const Run* run,
105 SkScalar runOffsetInLine,
106 SkScalar textOffsetInRunInLine,
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400107 bool includeGhostSpaces,
108 bool limitToClusters) const;
109
110 LineMetrics getMetrics() const;
Julia Lavrova526df262019-08-21 17:49:44 -0400111
Julia Lavrova89e678d2020-01-28 10:43:31 -0500112 SkRect extendHeight(const ClipContext& context) const;
113
Julia Lavrova9588a642020-04-30 11:31:25 -0400114 SkScalar metricsWithoutMultiplier(TextHeightBehavior correction);
115 void shiftVertically(SkScalar shift) { fOffset.fY += shift; }
116
Julia Lavrova6bdbd3d2020-05-06 12:03:17 -0400117 bool endsWithHardLineBreak() const;
118
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400119private:
Julia Lavrova5207f352019-06-21 12:22:32 -0400120
Ben Wagner0b13cec2020-05-18 10:52:23 -0400121 std::unique_ptr<Run> shapeEllipsis(const SkString& ellipsis, Run* run);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400122 void justify(SkScalar maxWidth);
123
Julia Lavrovab6030fb2020-09-08 11:01:49 -0400124 SkRect paintText(SkCanvas* canvas, SkScalar x, SkScalar y, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
125 void paintBackground(SkCanvas* canvas, SkScalar x, SkScalar y, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
126 SkRect paintShadow(SkCanvas* canvas, SkScalar x, SkScalar y, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
127 void paintDecorations(SkCanvas* canvas, SkScalar x, SkScalar y, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400128
Julia Lavrovaa0708e82020-02-28 12:14:58 -0500129 void shiftCluster(const Cluster* cluster, SkScalar shift, SkScalar prevShift);
130
Julia Lavrova2aa72452020-08-03 15:18:41 -0400131 ParagraphImpl* fOwner;
Julia Lavrova5207f352019-06-21 12:22:32 -0400132 BlockRange fBlockRange;
133 TextRange fTextRange;
134 TextRange fTextWithWhitespacesRange;
135 ClusterRange fClusterRange;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400136 ClusterRange fGhostClusterRange;
Ben Wagnerc0872212020-05-27 22:13:55 -0400137 // Avoid the malloc/free in the common case of one run per line
138 SkSTArray<1, size_t, true> fRunsInVisualOrder;
Julia Lavrova5207f352019-06-21 12:22:32 -0400139 SkVector fAdvance; // Text size
140 SkVector fOffset; // Text position
Julia Lavrova6bdbd3d2020-05-06 12:03:17 -0400141 SkScalar fShift; // Let right
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400142 SkScalar fWidthWithSpaces;
Ben Wagner0b13cec2020-05-18 10:52:23 -0400143 std::unique_ptr<Run> fEllipsis; // In case the line ends with the ellipsis
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400144 InternalLineMetrics fSizes; // Line metrics as a max of all run metrics and struts
145 InternalLineMetrics fMaxRunMetrics; // No struts - need it for GetRectForRange(max height)
Julia Lavrova5207f352019-06-21 12:22:32 -0400146 bool fHasBackground;
147 bool fHasShadows;
148 bool fHasDecorations;
Julia Lavrovadd1de252020-05-08 11:53:19 -0400149
150 LineMetricStyle fAscentStyle;
151 LineMetricStyle fDescentStyle;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400152};
153} // namespace textlayout
154} // namespace skia
155
156#endif // TextLine_DEFINED