blob: c5f51560b1b77018c4cf84ef780a796a45777baa [file] [log] [blame]
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001// Copyright 2019 Google LLC.
2#ifndef ParagraphImpl_DEFINED
3#define ParagraphImpl_DEFINED
4
Julia Lavrovaa3552c52019-05-30 16:12:56 -04005#include "include/core/SkPicture.h"
Mike Klein52337de2019-07-25 09:00:52 -05006#include "include/private/SkMutex.h"
Greg Danielf91aeb22019-06-18 09:58:02 -04007#include "include/private/SkTHash.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04008#include "modules/skparagraph/include/Paragraph.h"
9#include "modules/skparagraph/include/ParagraphStyle.h"
10#include "modules/skparagraph/include/TextStyle.h"
Mike Klein52337de2019-07-25 09:00:52 -050011#include "modules/skparagraph/src/FontResolver.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040012#include "modules/skparagraph/src/Run.h"
13#include "modules/skparagraph/src/TextLine.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040014
15class SkCanvas;
16
17namespace skia {
18namespace textlayout {
19
20template <typename T> bool operator==(const SkSpan<T>& a, const SkSpan<T>& b) {
21 return a.size() == b.size() && a.begin() == b.begin();
22}
23
24template <typename T> bool operator<=(const SkSpan<T>& a, const SkSpan<T>& b) {
25 return a.begin() >= b.begin() && a.end() <= b.end();
26}
27
Julia Lavrova5207f352019-06-21 12:22:32 -040028template <typename TStyle>
29struct StyleBlock {
30 StyleBlock() : fRange(EMPTY_RANGE), fStyle() { }
31 StyleBlock(size_t start, size_t end, const TStyle& style) : fRange(start, end), fStyle(style) {}
32 StyleBlock(TextRange textRange, const TStyle& style) : fRange(textRange), fStyle(style) {}
33 void add(TextRange tail) {
34 SkASSERT(fRange.end == tail.start);
35 fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width());
36 }
37 TextRange fRange;
38 TStyle fStyle;
39};
40
Julia Lavrovaa3552c52019-05-30 16:12:56 -040041class ParagraphImpl final : public Paragraph {
42public:
Julia Lavrova5207f352019-06-21 12:22:32 -040043
Julia Lavrovaa3552c52019-05-30 16:12:56 -040044 ParagraphImpl(const SkString& text,
45 ParagraphStyle style,
Julia Lavrova5207f352019-06-21 12:22:32 -040046 SkTArray<Block, true> blocks,
Julia Lavrova35f88222019-06-21 12:22:32 -040047 sk_sp<FontCollection> fonts);
Julia Lavrovaa3552c52019-05-30 16:12:56 -040048
49 ParagraphImpl(const std::u16string& utf16text,
50 ParagraphStyle style,
Julia Lavrova5207f352019-06-21 12:22:32 -040051 SkTArray<Block, true> blocks,
Julia Lavrovaa3552c52019-05-30 16:12:56 -040052 sk_sp<FontCollection> fonts);
53 ~ParagraphImpl() override;
54
55 void layout(SkScalar width) override;
56 void paint(SkCanvas* canvas, SkScalar x, SkScalar y) override;
57 std::vector<TextBox> getRectsForRange(unsigned start,
58 unsigned end,
59 RectHeightStyle rectHeightStyle,
60 RectWidthStyle rectWidthStyle) override;
61 PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override;
62 SkRange<size_t> getWordBoundary(unsigned offset) override;
63 bool didExceedMaxLines() override {
64 return !fParagraphStyle.unlimited_lines() && fLines.size() > fParagraphStyle.getMaxLines();
65 }
66
67 size_t lineNumber() override { return fLines.size(); }
68
Julia Lavrova5207f352019-06-21 12:22:32 -040069 TextLine& addLine(SkVector offset, SkVector advance, TextRange text, TextRange textWithSpaces,
Julia Lavrovadb9f6692019-08-01 16:02:17 -040070 ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar AddLineToParagraph,
71 LineMetrics sizes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -040072
73 SkSpan<const char> text() const { return fTextSpan; }
Julia Lavrova5207f352019-06-21 12:22:32 -040074 InternalState state() const { return fState; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040075 SkSpan<Run> runs() { return SkSpan<Run>(fRuns.data(), fRuns.size()); }
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -040076 const SkTArray<FontDescr>& switches() const { return fFontResolver.switches(); }
Julia Lavrova5207f352019-06-21 12:22:32 -040077 SkSpan<Block> styles() {
78 return SkSpan<Block>(fTextStyles.data(), fTextStyles.size());
Julia Lavrovaa3552c52019-05-30 16:12:56 -040079 }
80 SkSpan<TextLine> lines() { return SkSpan<TextLine>(fLines.data(), fLines.size()); }
Julia Lavrovadb9f6692019-08-01 16:02:17 -040081 const ParagraphStyle& paragraphStyle() const { return fParagraphStyle; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040082 SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); }
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -040083 sk_sp<FontCollection> fontCollection() const { return fFontCollection; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040084 void formatLines(SkScalar maxWidth);
85
Julia Lavrova5207f352019-06-21 12:22:32 -040086 void shiftCluster(ClusterIndex index, SkScalar shift) {
87 auto& cluster = fClusters[index];
88 auto& run = fRunShifts[cluster.runIndex()];
89 for (size_t pos = cluster.startPos(); pos < cluster.endPos(); ++pos) {
90 run.fShifts[pos] = shift;
91 }
92 }
93
94 SkScalar posShift(RunIndex index, size_t pos) const {
95 if (fRunShifts.count() == 0) return 0.0;
96 return fRunShifts[index].fShifts[pos];
97 }
98
99 SkScalar lineShift(size_t index) { return fLines[index].shift(); }
100
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400101 bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); }
102 bool strutForceHeight() const {
103 return paragraphStyle().getStrutStyle().getForceStrutHeight();
104 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400105 bool strutHeightOverride() const {
106 return paragraphStyle().getStrutStyle().getHeightOverride();
107 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400108 LineMetrics strutMetrics() const { return fStrutMetrics; }
109
Julia Lavrova5207f352019-06-21 12:22:32 -0400110 Measurement measurement() {
111 return {
112 fAlphabeticBaseline,
113 fIdeographicBaseline,
114 fHeight,
115 fWidth,
116 fMaxIntrinsicWidth,
117 fMinIntrinsicWidth,
118 };
119 }
120 void setMeasurement(Measurement m) {
121 fAlphabeticBaseline = m.fAlphabeticBaseline;
122 fIdeographicBaseline = m.fIdeographicBaseline;
123 fHeight = m.fHeight;
124 fWidth = m.fWidth;
125 fMaxIntrinsicWidth = m.fMaxIntrinsicWidth;
126 fMinIntrinsicWidth = m.fMinIntrinsicWidth;
127 }
Julia Lavrova9af5cc42019-06-19 13:32:01 -0400128
Julia Lavrova5207f352019-06-21 12:22:32 -0400129 SkSpan<const char> text(TextRange textRange);
130 SkSpan<Cluster> clusters(ClusterRange clusterRange);
131 Cluster& cluster(ClusterIndex clusterIndex);
132 Run& run(RunIndex runIndex);
133 SkSpan<Block> blocks(BlockRange blockRange);
134 Block& block(BlockIndex blockIndex);
135
136 void markDirty() override { fState = kUnknown; }
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -0400137 FontResolver& getResolver() { return fFontResolver; }
Julia Lavrova5207f352019-06-21 12:22:32 -0400138 void setState(InternalState state);
Julia Lavrova5207f352019-06-21 12:22:32 -0400139 sk_sp<SkPicture> getPicture() { return fPicture; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400140
141 void resetContext();
142 void resolveStrut();
Julia Lavrova5207f352019-06-21 12:22:32 -0400143 void resetRunShifts();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400144 void buildClusterTable();
Julia Lavrova5207f352019-06-21 12:22:32 -0400145 void markLineBreaks();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400146 bool shapeTextIntoEndlessLine();
147 void breakShapedTextIntoLines(SkScalar maxWidth);
148 void paintLinesIntoPicture();
149
Julia Lavrova5207f352019-06-21 12:22:32 -0400150private:
151 friend class ParagraphBuilder;
152 friend class ParagraphCacheKey;
153 friend class ParagraphCacheValue;
154 friend class ParagraphCache;
155
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400156 friend class TextWrapper;
157
Julia Lavrova5207f352019-06-21 12:22:32 -0400158 BlockRange findAllBlocks(TextRange textRange);
159 void extractStyles();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400160
161 // Input
Julia Lavrova5207f352019-06-21 12:22:32 -0400162 SkTArray<StyleBlock<SkScalar>> fLetterSpaceStyles;
163 SkTArray<StyleBlock<SkScalar>> fWordSpaceStyles;
164 SkTArray<StyleBlock<SkPaint>> fBackgroundStyles;
165 SkTArray<StyleBlock<SkPaint>> fForegroundStyles;
166 SkTArray<StyleBlock<std::vector<TextShadow>>> fShadowStyles;
167 SkTArray<StyleBlock<Decoration>> fDecorationStyles;
168 SkTArray<Block, true> fTextStyles; // TODO: take out only the font stuff
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400169 SkString fText;
170 SkSpan<const char> fTextSpan;
171
172 // Internal structures
Julia Lavrova5207f352019-06-21 12:22:32 -0400173 InternalState fState;
174 SkTArray<Run> fRuns; // kShaped
175 SkTArray<Cluster, true> fClusters; // kClusterized (cached: text, word spacing, letter spacing, resolved fonts)
176
177 SkTArray<RunShifts, true> fRunShifts;
178 SkTArray<TextLine, true> fLines; // kFormatted (cached: width, max lines, ellipsis, text align)
179 sk_sp<SkPicture> fPicture; // kRecorded (cached: text styles)
180
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400181 LineMetrics fStrutMetrics;
Julia Lavrova35f88222019-06-21 12:22:32 -0400182 FontResolver fFontResolver;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400183
Julia Lavrova9af5cc42019-06-19 13:32:01 -0400184 SkScalar fOldWidth;
Julia Lavrova5207f352019-06-21 12:22:32 -0400185 SkScalar fOldHeight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400186 SkScalar fMaxWidthWithTrailingSpaces;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400187};
188} // namespace textlayout
189} // namespace skia
190
191#endif // ParagraphImpl_DEFINED