blob: fd39e10cbc900b27951f49abc915af9be848e140 [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 Lavrova916a9042019-08-08 16:51:27 -04005#include <unicode/brkiter.h>
6#include <unicode/ubidi.h>
7#include <unicode/unistr.h>
8#include <unicode/urename.h>
Julia Lavrovaa3552c52019-05-30 16:12:56 -04009#include "include/core/SkPicture.h"
Mike Klein52337de2019-07-25 09:00:52 -050010#include "include/private/SkMutex.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040011#include "include/private/SkTHash.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040012#include "modules/skparagraph/include/Paragraph.h"
13#include "modules/skparagraph/include/ParagraphStyle.h"
14#include "modules/skparagraph/include/TextStyle.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040015#include "modules/skparagraph/src/Run.h"
16#include "modules/skparagraph/src/TextLine.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040017
18class SkCanvas;
19
20namespace skia {
21namespace textlayout {
22
23template <typename T> bool operator==(const SkSpan<T>& a, const SkSpan<T>& b) {
24 return a.size() == b.size() && a.begin() == b.begin();
25}
26
27template <typename T> bool operator<=(const SkSpan<T>& a, const SkSpan<T>& b) {
28 return a.begin() >= b.begin() && a.end() <= b.end();
29}
30
Julia Lavrova5207f352019-06-21 12:22:32 -040031template <typename TStyle>
32struct StyleBlock {
33 StyleBlock() : fRange(EMPTY_RANGE), fStyle() { }
34 StyleBlock(size_t start, size_t end, const TStyle& style) : fRange(start, end), fStyle(style) {}
35 StyleBlock(TextRange textRange, const TStyle& style) : fRange(textRange), fStyle(style) {}
36 void add(TextRange tail) {
37 SkASSERT(fRange.end == tail.start);
38 fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width());
39 }
40 TextRange fRange;
41 TStyle fStyle;
42};
43
Julia Lavrova2e30fde2019-10-09 09:43:02 -040044struct ResolvedFontDescriptor {
45
46 ResolvedFontDescriptor(TextIndex index, SkFont font)
47 : fFont(font), fTextStart(index) { }
48 SkFont fFont;
49 TextIndex fTextStart;
50};
51
Julia Lavrovac88a3bc2020-01-23 10:16:26 -050052struct BidiRegion {
53 BidiRegion(size_t start, size_t end, uint8_t dir)
54 : text(start, end), direction(dir) { }
55 TextRange text;
56 uint8_t direction;
57};
58
Julia Lavrova916a9042019-08-08 16:51:27 -040059class TextBreaker {
60public:
61 TextBreaker() : fInitialized(false), fPos(-1) {}
62
63 bool initialize(SkSpan<const char> text, UBreakIteratorType type);
64
65 bool initialized() const { return fInitialized; }
66
67 size_t first() {
68 fPos = ubrk_first(fIterator.get());
69 return eof() ? fSize : fPos;
70 }
71
72 size_t next() {
73 fPos = ubrk_next(fIterator.get());
74 return eof() ? fSize : fPos;
75 }
76
77 size_t preceding(size_t offset) {
78 auto pos = ubrk_preceding(fIterator.get(), offset);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -040079 return pos == icu::BreakIterator::DONE ? 0 : pos;
Julia Lavrova916a9042019-08-08 16:51:27 -040080 }
81
82 size_t following(size_t offset) {
83 auto pos = ubrk_following(fIterator.get(), offset);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -040084 return pos == icu::BreakIterator::DONE ? fSize : pos;
Julia Lavrova916a9042019-08-08 16:51:27 -040085 }
86
87 int32_t status() { return ubrk_getRuleStatus(fIterator.get()); }
88
89 bool eof() { return fPos == icu::BreakIterator::DONE; }
90
91private:
Ben Wagner723a8772019-08-16 11:36:58 -040092 std::unique_ptr<UBreakIterator, SkFunctionWrapper<decltype(ubrk_close), ubrk_close>> fIterator;
Julia Lavrova916a9042019-08-08 16:51:27 -040093 bool fInitialized;
94 int32_t fPos;
95 size_t fSize;
96};
97
Julia Lavrovaa3552c52019-05-30 16:12:56 -040098class ParagraphImpl final : public Paragraph {
Julia Lavrovac2228562019-08-08 16:51:27 -040099
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400100public:
Julia Lavrova5207f352019-06-21 12:22:32 -0400101
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400102 ParagraphImpl(const SkString& text,
103 ParagraphStyle style,
Julia Lavrova5207f352019-06-21 12:22:32 -0400104 SkTArray<Block, true> blocks,
Julia Lavrova916a9042019-08-08 16:51:27 -0400105 SkTArray<Placeholder, true> placeholders,
Julia Lavrova35f88222019-06-21 12:22:32 -0400106 sk_sp<FontCollection> fonts);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400107
108 ParagraphImpl(const std::u16string& utf16text,
Julia Lavrova916a9042019-08-08 16:51:27 -0400109 ParagraphStyle style,
110 SkTArray<Block, true> blocks,
111 SkTArray<Placeholder, true> placeholders,
112 sk_sp<FontCollection> fonts);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400113 ~ParagraphImpl() override;
114
115 void layout(SkScalar width) override;
116 void paint(SkCanvas* canvas, SkScalar x, SkScalar y) override;
117 std::vector<TextBox> getRectsForRange(unsigned start,
118 unsigned end,
119 RectHeightStyle rectHeightStyle,
120 RectWidthStyle rectWidthStyle) override;
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400121 std::vector<TextBox> getRectsForPlaceholders() override;
122 void getLineMetrics(std::vector<LineMetrics>&) override;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400123 PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override;
124 SkRange<size_t> getWordBoundary(unsigned offset) override;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400125
126 size_t lineNumber() override { return fLines.size(); }
127
Julia Lavrova5207f352019-06-21 12:22:32 -0400128 TextLine& addLine(SkVector offset, SkVector advance, TextRange text, TextRange textWithSpaces,
Julia Lavrova2ea20ea2020-01-22 10:56:53 -0500129 ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar widthWithSpaces,
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400130 InternalLineMetrics sizes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400131
Julia Lavrovaa40db422019-08-21 13:49:15 -0400132 SkSpan<const char> text() const { return SkSpan<const char>(fText.c_str(), fText.size()); }
Julia Lavrova5207f352019-06-21 12:22:32 -0400133 InternalState state() const { return fState; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400134 SkSpan<Run> runs() { return SkSpan<Run>(fRuns.data(), fRuns.size()); }
Julia Lavrova5207f352019-06-21 12:22:32 -0400135 SkSpan<Block> styles() {
136 return SkSpan<Block>(fTextStyles.data(), fTextStyles.size());
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400137 }
138 SkSpan<TextLine> lines() { return SkSpan<TextLine>(fLines.data(), fLines.size()); }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400139 const ParagraphStyle& paragraphStyle() const { return fParagraphStyle; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400140 SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); }
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -0400141 sk_sp<FontCollection> fontCollection() const { return fFontCollection; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400142 void formatLines(SkScalar maxWidth);
143
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400144 void shiftCluster(ClusterIndex index, SkScalar shift, SkScalar lastShift) {
Julia Lavrova5207f352019-06-21 12:22:32 -0400145 auto& cluster = fClusters[index];
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400146 auto& runShift = fRunShifts[cluster.runIndex()];
147 auto& run = fRuns[cluster.runIndex()];
148 auto start = cluster.startPos();
149 auto end = cluster.endPos();
150 if (!run.leftToRight()) {
151 runShift.fShifts[start] = lastShift;
152 ++start;
153 ++end;
154 }
155 for (size_t pos = start; pos < end; ++pos) {
156 runShift.fShifts[pos] = shift;
Julia Lavrova5207f352019-06-21 12:22:32 -0400157 }
158 }
159
160 SkScalar posShift(RunIndex index, size_t pos) const {
161 if (fRunShifts.count() == 0) return 0.0;
162 return fRunShifts[index].fShifts[pos];
163 }
164
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400165 bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); }
166 bool strutForceHeight() const {
167 return paragraphStyle().getStrutStyle().getForceStrutHeight();
168 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400169 bool strutHeightOverride() const {
170 return paragraphStyle().getStrutStyle().getHeightOverride();
171 }
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400172 InternalLineMetrics strutMetrics() const { return fStrutMetrics; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400173
Julia Lavrova5207f352019-06-21 12:22:32 -0400174 SkSpan<const char> text(TextRange textRange);
175 SkSpan<Cluster> clusters(ClusterRange clusterRange);
176 Cluster& cluster(ClusterIndex clusterIndex);
177 Run& run(RunIndex runIndex);
Julia Lavrova526df262019-08-21 17:49:44 -0400178 Run& runByCluster(ClusterIndex clusterIndex);
Julia Lavrova5207f352019-06-21 12:22:32 -0400179 SkSpan<Block> blocks(BlockRange blockRange);
180 Block& block(BlockIndex blockIndex);
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400181 SkTArray<ResolvedFontDescriptor> resolvedFonts() const { return fFontSwitches; }
Julia Lavrova5207f352019-06-21 12:22:32 -0400182
183 void markDirty() override { fState = kUnknown; }
Julia Lavrova3281b962019-12-02 11:32:25 -0500184
185 int32_t unresolvedGlyphs() override;
186
Julia Lavrova5207f352019-06-21 12:22:32 -0400187 void setState(InternalState state);
Julia Lavrova5207f352019-06-21 12:22:32 -0400188 sk_sp<SkPicture> getPicture() { return fPicture; }
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400189 SkRect getBoundaries() const { return fOrigin; }
Julia Lavrova916a9042019-08-08 16:51:27 -0400190
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400191 void resetContext();
192 void resolveStrut();
Julia Lavrova5207f352019-06-21 12:22:32 -0400193 void resetRunShifts();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400194 void buildClusterTable();
Julia Lavrova5207f352019-06-21 12:22:32 -0400195 void markLineBreaks();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400196 bool shapeTextIntoEndlessLine();
197 void breakShapedTextIntoLines(SkScalar maxWidth);
198 void paintLinesIntoPicture();
199
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400200 void updateTextAlign(TextAlign textAlign) override;
201 void updateText(size_t from, SkString text) override;
202 void updateFontSize(size_t from, size_t to, SkScalar fontSize) override;
203 void updateForegroundPaint(size_t from, size_t to, SkPaint paint) override;
204 void updateBackgroundPaint(size_t from, size_t to, SkPaint paint) override;
205
Jason Simmons22bb52e2019-12-05 17:56:59 -0800206 InternalLineMetrics getEmptyMetrics() const { return fEmptyMetrics; }
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400207 InternalLineMetrics getStrutMetrics() const { return fStrutMetrics; }
208
Julia Lavrova90bfd1c2019-12-04 11:43:32 -0500209 BlockRange findAllBlocks(TextRange textRange);
210
Julia Lavrova5207f352019-06-21 12:22:32 -0400211private:
212 friend class ParagraphBuilder;
213 friend class ParagraphCacheKey;
214 friend class ParagraphCacheValue;
215 friend class ParagraphCache;
216
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400217 friend class TextWrapper;
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400218 friend class OneLineShaper;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400219
Julia Lavrova9bd83512020-01-15 14:46:35 -0500220 void calculateBoundaries();
Julia Lavrova5207f352019-06-21 12:22:32 -0400221 void extractStyles();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400222
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400223 void markGraphemes16();
Julia Lavrovac2228562019-08-08 16:51:27 -0400224 void markGraphemes();
225
Jason Simmons22bb52e2019-12-05 17:56:59 -0800226 void computeEmptyMetrics();
227
Julia Lavrovac88a3bc2020-01-23 10:16:26 -0500228 bool calculateBidiRegions(SkTArray<BidiRegion>* regions);
229
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400230 // Input
Julia Lavrova5207f352019-06-21 12:22:32 -0400231 SkTArray<StyleBlock<SkScalar>> fLetterSpaceStyles;
232 SkTArray<StyleBlock<SkScalar>> fWordSpaceStyles;
233 SkTArray<StyleBlock<SkPaint>> fBackgroundStyles;
234 SkTArray<StyleBlock<SkPaint>> fForegroundStyles;
235 SkTArray<StyleBlock<std::vector<TextShadow>>> fShadowStyles;
236 SkTArray<StyleBlock<Decoration>> fDecorationStyles;
237 SkTArray<Block, true> fTextStyles; // TODO: take out only the font stuff
Julia Lavrova916a9042019-08-08 16:51:27 -0400238 SkTArray<Placeholder, true> fPlaceholders;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400239 SkString fText;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400240
241 // Internal structures
Julia Lavrova5207f352019-06-21 12:22:32 -0400242 InternalState fState;
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400243 SkTArray<Run, false> fRuns; // kShaped
Julia Lavrova5207f352019-06-21 12:22:32 -0400244 SkTArray<Cluster, true> fClusters; // kClusterized (cached: text, word spacing, letter spacing, resolved fonts)
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400245 SkTArray<Grapheme, true> fGraphemes16;
Julia Lavrovac2228562019-08-08 16:51:27 -0400246 SkTArray<Codepoint, true> fCodePoints;
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400247 SkTHashSet<size_t> fGraphemes;
Julia Lavrova3281b962019-12-02 11:32:25 -0500248 size_t fUnresolvedGlyphs;
Julia Lavrova5207f352019-06-21 12:22:32 -0400249
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400250 SkTArray<RunShifts, false> fRunShifts;
Julia Lavrova5207f352019-06-21 12:22:32 -0400251 SkTArray<TextLine, true> fLines; // kFormatted (cached: width, max lines, ellipsis, text align)
252 sk_sp<SkPicture> fPicture; // kRecorded (cached: text styles)
253
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400254 SkTArray<ResolvedFontDescriptor> fFontSwitches;
255
Jason Simmons22bb52e2019-12-05 17:56:59 -0800256 InternalLineMetrics fEmptyMetrics;
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400257 InternalLineMetrics fStrutMetrics;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400258
Julia Lavrova9af5cc42019-06-19 13:32:01 -0400259 SkScalar fOldWidth;
Julia Lavrova5207f352019-06-21 12:22:32 -0400260 SkScalar fOldHeight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400261 SkScalar fMaxWidthWithTrailingSpaces;
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400262 SkRect fOrigin;
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400263 std::vector<size_t> fWords;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400264};
265} // namespace textlayout
266} // namespace skia
267
268#endif // ParagraphImpl_DEFINED