blob: 3a1b1fd1d32ba7b0ad6c2bbb3e77e99afc3f214e [file] [log] [blame]
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001// Copyright 2019 Google LLC.
2#ifndef ParagraphImpl_DEFINED
3#define ParagraphImpl_DEFINED
4
Ben Wagner4ca7a812020-05-28 13:48:18 -04005#include "include/core/SkFont.h"
6#include "include/core/SkPaint.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04007#include "include/core/SkPicture.h"
Ben Wagner4ca7a812020-05-28 13:48:18 -04008#include "include/core/SkPoint.h"
9#include "include/core/SkRect.h"
10#include "include/core/SkRefCnt.h"
11#include "include/core/SkScalar.h"
12#include "include/core/SkString.h"
13#include "include/core/SkTypes.h"
14#include "include/private/SkTArray.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040015#include "include/private/SkTHash.h"
Ben Wagner4ca7a812020-05-28 13:48:18 -040016#include "include/private/SkTemplates.h"
17#include "modules/skparagraph/include/DartTypes.h"
18#include "modules/skparagraph/include/FontCollection.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040019#include "modules/skparagraph/include/Paragraph.h"
Ben Wagner4ca7a812020-05-28 13:48:18 -040020#include "modules/skparagraph/include/ParagraphCache.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040021#include "modules/skparagraph/include/ParagraphStyle.h"
Ben Wagner4ca7a812020-05-28 13:48:18 -040022#include "modules/skparagraph/include/TextShadow.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040023#include "modules/skparagraph/include/TextStyle.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040024#include "modules/skparagraph/src/Run.h"
Ben Wagner4ca7a812020-05-28 13:48:18 -040025#include "src/core/SkSpan.h"
26
27#include <unicode/ubrk.h>
28#include <memory>
29#include <string>
30#include <vector>
Julia Lavrovaa3552c52019-05-30 16:12:56 -040031
32class SkCanvas;
33
34namespace skia {
35namespace textlayout {
36
Ben Wagner4ca7a812020-05-28 13:48:18 -040037class LineMetrics;
38class TextLine;
39
Julia Lavrovaa3552c52019-05-30 16:12:56 -040040template <typename T> bool operator==(const SkSpan<T>& a, const SkSpan<T>& b) {
41 return a.size() == b.size() && a.begin() == b.begin();
42}
43
44template <typename T> bool operator<=(const SkSpan<T>& a, const SkSpan<T>& b) {
45 return a.begin() >= b.begin() && a.end() <= b.end();
46}
47
Julia Lavrova5207f352019-06-21 12:22:32 -040048template <typename TStyle>
49struct StyleBlock {
50 StyleBlock() : fRange(EMPTY_RANGE), fStyle() { }
51 StyleBlock(size_t start, size_t end, const TStyle& style) : fRange(start, end), fStyle(style) {}
52 StyleBlock(TextRange textRange, const TStyle& style) : fRange(textRange), fStyle(style) {}
53 void add(TextRange tail) {
54 SkASSERT(fRange.end == tail.start);
55 fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width());
56 }
57 TextRange fRange;
58 TStyle fStyle;
59};
60
Julia Lavrova2e30fde2019-10-09 09:43:02 -040061struct ResolvedFontDescriptor {
62
63 ResolvedFontDescriptor(TextIndex index, SkFont font)
64 : fFont(font), fTextStart(index) { }
65 SkFont fFont;
66 TextIndex fTextStart;
67};
68
Julia Lavrovac88a3bc2020-01-23 10:16:26 -050069struct BidiRegion {
70 BidiRegion(size_t start, size_t end, uint8_t dir)
71 : text(start, end), direction(dir) { }
72 TextRange text;
73 uint8_t direction;
74};
75
Julia Lavrova916a9042019-08-08 16:51:27 -040076class TextBreaker {
77public:
78 TextBreaker() : fInitialized(false), fPos(-1) {}
79
80 bool initialize(SkSpan<const char> text, UBreakIteratorType type);
81
82 bool initialized() const { return fInitialized; }
83
84 size_t first() {
85 fPos = ubrk_first(fIterator.get());
86 return eof() ? fSize : fPos;
87 }
88
89 size_t next() {
90 fPos = ubrk_next(fIterator.get());
91 return eof() ? fSize : fPos;
92 }
93
94 size_t preceding(size_t offset) {
95 auto pos = ubrk_preceding(fIterator.get(), offset);
Ben Wagner4ca7a812020-05-28 13:48:18 -040096 return pos == UBRK_DONE ? 0 : pos;
Julia Lavrova916a9042019-08-08 16:51:27 -040097 }
98
99 size_t following(size_t offset) {
100 auto pos = ubrk_following(fIterator.get(), offset);
Ben Wagner4ca7a812020-05-28 13:48:18 -0400101 return pos == UBRK_DONE ? fSize : pos;
Julia Lavrova916a9042019-08-08 16:51:27 -0400102 }
103
104 int32_t status() { return ubrk_getRuleStatus(fIterator.get()); }
105
Ben Wagner4ca7a812020-05-28 13:48:18 -0400106 bool eof() { return fPos == UBRK_DONE; }
Julia Lavrova916a9042019-08-08 16:51:27 -0400107
108private:
Ben Wagner723a8772019-08-16 11:36:58 -0400109 std::unique_ptr<UBreakIterator, SkFunctionWrapper<decltype(ubrk_close), ubrk_close>> fIterator;
Julia Lavrova916a9042019-08-08 16:51:27 -0400110 bool fInitialized;
111 int32_t fPos;
112 size_t fSize;
113};
114
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400115class ParagraphImpl final : public Paragraph {
Julia Lavrovac2228562019-08-08 16:51:27 -0400116
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400117public:
Julia Lavrova5207f352019-06-21 12:22:32 -0400118
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400119 ParagraphImpl(const SkString& text,
120 ParagraphStyle style,
Julia Lavrova5207f352019-06-21 12:22:32 -0400121 SkTArray<Block, true> blocks,
Julia Lavrova916a9042019-08-08 16:51:27 -0400122 SkTArray<Placeholder, true> placeholders,
Julia Lavrova35f88222019-06-21 12:22:32 -0400123 sk_sp<FontCollection> fonts);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400124
125 ParagraphImpl(const std::u16string& utf16text,
Julia Lavrova916a9042019-08-08 16:51:27 -0400126 ParagraphStyle style,
127 SkTArray<Block, true> blocks,
128 SkTArray<Placeholder, true> placeholders,
129 sk_sp<FontCollection> fonts);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400130 ~ParagraphImpl() override;
131
132 void layout(SkScalar width) override;
133 void paint(SkCanvas* canvas, SkScalar x, SkScalar y) override;
134 std::vector<TextBox> getRectsForRange(unsigned start,
135 unsigned end,
136 RectHeightStyle rectHeightStyle,
137 RectWidthStyle rectWidthStyle) override;
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400138 std::vector<TextBox> getRectsForPlaceholders() override;
139 void getLineMetrics(std::vector<LineMetrics>&) override;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400140 PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override;
141 SkRange<size_t> getWordBoundary(unsigned offset) override;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400142
143 size_t lineNumber() override { return fLines.size(); }
144
Julia Lavrova5207f352019-06-21 12:22:32 -0400145 TextLine& addLine(SkVector offset, SkVector advance, TextRange text, TextRange textWithSpaces,
Julia Lavrova2ea20ea2020-01-22 10:56:53 -0500146 ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar widthWithSpaces,
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400147 InternalLineMetrics sizes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400148
Julia Lavrovaa40db422019-08-21 13:49:15 -0400149 SkSpan<const char> text() const { return SkSpan<const char>(fText.c_str(), fText.size()); }
Julia Lavrova5207f352019-06-21 12:22:32 -0400150 InternalState state() const { return fState; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400151 SkSpan<Run> runs() { return SkSpan<Run>(fRuns.data(), fRuns.size()); }
Julia Lavrova5207f352019-06-21 12:22:32 -0400152 SkSpan<Block> styles() {
153 return SkSpan<Block>(fTextStyles.data(), fTextStyles.size());
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400154 }
Julia Lavrovac0360582020-02-05 10:17:53 -0500155 SkSpan<Placeholder> placeholders() {
156 return SkSpan<Placeholder>(fPlaceholders.data(), fPlaceholders.size());
157 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400158 SkSpan<TextLine> lines() { return SkSpan<TextLine>(fLines.data(), fLines.size()); }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400159 const ParagraphStyle& paragraphStyle() const { return fParagraphStyle; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400160 SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); }
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -0400161 sk_sp<FontCollection> fontCollection() const { return fFontCollection; }
Julia Lavrovaa169b002020-03-23 13:39:52 -0400162 const SkTHashSet<size_t>& graphemes() const { return fGraphemes; }
Julia Lavrova8335ab62020-04-27 15:49:53 -0400163 SkSpan<Codepoint> codepoints(){ return SkSpan<Codepoint>(fCodePoints.begin(), fCodePoints.size()); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400164 void formatLines(SkScalar maxWidth);
165
166 bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); }
167 bool strutForceHeight() const {
168 return paragraphStyle().getStrutStyle().getForceStrutHeight();
169 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400170 bool strutHeightOverride() const {
171 return paragraphStyle().getStrutStyle().getHeightOverride();
172 }
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400173 InternalLineMetrics strutMetrics() const { return fStrutMetrics; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400174
Julia Lavrova5207f352019-06-21 12:22:32 -0400175 SkSpan<const char> text(TextRange textRange);
176 SkSpan<Cluster> clusters(ClusterRange clusterRange);
177 Cluster& cluster(ClusterIndex clusterIndex);
178 Run& run(RunIndex runIndex);
Julia Lavrova526df262019-08-21 17:49:44 -0400179 Run& runByCluster(ClusterIndex clusterIndex);
Julia Lavrova5207f352019-06-21 12:22:32 -0400180 SkSpan<Block> blocks(BlockRange blockRange);
181 Block& block(BlockIndex blockIndex);
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400182 SkTArray<ResolvedFontDescriptor> resolvedFonts() const { return fFontSwitches; }
Julia Lavrova5207f352019-06-21 12:22:32 -0400183
184 void markDirty() override { fState = kUnknown; }
Julia Lavrova3281b962019-12-02 11:32:25 -0500185
186 int32_t unresolvedGlyphs() override;
187
Julia Lavrova5207f352019-06-21 12:22:32 -0400188 void setState(InternalState state);
Julia Lavrova5207f352019-06-21 12:22:32 -0400189 sk_sp<SkPicture> getPicture() { return fPicture; }
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400190 SkRect getBoundaries() const { return fOrigin; }
Julia Lavrova916a9042019-08-08 16:51:27 -0400191
Julia Lavrova8335ab62020-04-27 15:49:53 -0400192 SkScalar widthWithTrailingSpaces() { return fMaxWidthWithTrailingSpaces; }
193
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400194 void resetContext();
195 void resolveStrut();
196 void buildClusterTable();
Julia Lavrova5207f352019-06-21 12:22:32 -0400197 void markLineBreaks();
Julia Lavrova8335ab62020-04-27 15:49:53 -0400198 void spaceGlyphs();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400199 bool shapeTextIntoEndlessLine();
200 void breakShapedTextIntoLines(SkScalar maxWidth);
201 void paintLinesIntoPicture();
202
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400203 void updateTextAlign(TextAlign textAlign) override;
204 void updateText(size_t from, SkString text) override;
205 void updateFontSize(size_t from, size_t to, SkScalar fontSize) override;
206 void updateForegroundPaint(size_t from, size_t to, SkPaint paint) override;
207 void updateBackgroundPaint(size_t from, size_t to, SkPaint paint) override;
208
Jason Simmons22bb52e2019-12-05 17:56:59 -0800209 InternalLineMetrics getEmptyMetrics() const { return fEmptyMetrics; }
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400210 InternalLineMetrics getStrutMetrics() const { return fStrutMetrics; }
211
Julia Lavrova90bfd1c2019-12-04 11:43:32 -0500212 BlockRange findAllBlocks(TextRange textRange);
213
Julia Lavrovaa0708e82020-02-28 12:14:58 -0500214 void resetShifts() {
215 for (auto& run : fRuns) {
216 run.resetJustificationShifts();
217 run.resetShifts();
218 }
219 }
220
Julia Lavrova5207f352019-06-21 12:22:32 -0400221private:
222 friend class ParagraphBuilder;
223 friend class ParagraphCacheKey;
224 friend class ParagraphCacheValue;
225 friend class ParagraphCache;
226
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400227 friend class TextWrapper;
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400228 friend class OneLineShaper;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400229
Julia Lavrova9bd83512020-01-15 14:46:35 -0500230 void calculateBoundaries();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400231
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400232 void markGraphemes16();
Julia Lavrovac2228562019-08-08 16:51:27 -0400233 void markGraphemes();
234
Jason Simmons22bb52e2019-12-05 17:56:59 -0800235 void computeEmptyMetrics();
236
Julia Lavrovac88a3bc2020-01-23 10:16:26 -0500237 bool calculateBidiRegions(SkTArray<BidiRegion>* regions);
238
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400239 // Input
Julia Lavrova5207f352019-06-21 12:22:32 -0400240 SkTArray<StyleBlock<SkScalar>> fLetterSpaceStyles;
241 SkTArray<StyleBlock<SkScalar>> fWordSpaceStyles;
242 SkTArray<StyleBlock<SkPaint>> fBackgroundStyles;
243 SkTArray<StyleBlock<SkPaint>> fForegroundStyles;
244 SkTArray<StyleBlock<std::vector<TextShadow>>> fShadowStyles;
245 SkTArray<StyleBlock<Decoration>> fDecorationStyles;
246 SkTArray<Block, true> fTextStyles; // TODO: take out only the font stuff
Julia Lavrova916a9042019-08-08 16:51:27 -0400247 SkTArray<Placeholder, true> fPlaceholders;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400248 SkString fText;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400249
250 // Internal structures
Julia Lavrova5207f352019-06-21 12:22:32 -0400251 InternalState fState;
Julia Lavrovaa0708e82020-02-28 12:14:58 -0500252 SkTArray<Run, false> fRuns; // kShaped
Julia Lavrova5207f352019-06-21 12:22:32 -0400253 SkTArray<Cluster, true> fClusters; // kClusterized (cached: text, word spacing, letter spacing, resolved fonts)
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400254 SkTArray<Grapheme, true> fGraphemes16;
Julia Lavrovac2228562019-08-08 16:51:27 -0400255 SkTArray<Codepoint, true> fCodePoints;
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400256 SkTHashSet<size_t> fGraphemes;
Julia Lavrova3281b962019-12-02 11:32:25 -0500257 size_t fUnresolvedGlyphs;
Julia Lavrova5207f352019-06-21 12:22:32 -0400258
Ben Wagnerc0872212020-05-27 22:13:55 -0400259 SkTArray<TextLine, false> fLines; // kFormatted (cached: width, max lines, ellipsis, text align)
Julia Lavrova5207f352019-06-21 12:22:32 -0400260 sk_sp<SkPicture> fPicture; // kRecorded (cached: text styles)
261
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400262 SkTArray<ResolvedFontDescriptor> fFontSwitches;
263
Jason Simmons22bb52e2019-12-05 17:56:59 -0800264 InternalLineMetrics fEmptyMetrics;
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400265 InternalLineMetrics fStrutMetrics;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400266
Julia Lavrova9af5cc42019-06-19 13:32:01 -0400267 SkScalar fOldWidth;
Julia Lavrova5207f352019-06-21 12:22:32 -0400268 SkScalar fOldHeight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400269 SkScalar fMaxWidthWithTrailingSpaces;
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400270 SkRect fOrigin;
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400271 std::vector<size_t> fWords;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400272};
273} // namespace textlayout
274} // namespace skia
275
276#endif // ParagraphImpl_DEFINED