blob: 7f461585c65638e4d74cab1bc77925a1d838541e [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"
Julia Lavrova149f22d2020-05-27 10:38:35 -040014#include "include/private/SkBitmaskEnum.h"
Ben Wagner4ca7a812020-05-28 13:48:18 -040015#include "include/private/SkTArray.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040016#include "include/private/SkTHash.h"
Ben Wagner4ca7a812020-05-28 13:48:18 -040017#include "include/private/SkTemplates.h"
18#include "modules/skparagraph/include/DartTypes.h"
19#include "modules/skparagraph/include/FontCollection.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040020#include "modules/skparagraph/include/Paragraph.h"
Ben Wagner4ca7a812020-05-28 13:48:18 -040021#include "modules/skparagraph/include/ParagraphCache.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040022#include "modules/skparagraph/include/ParagraphStyle.h"
Ben Wagner4ca7a812020-05-28 13:48:18 -040023#include "modules/skparagraph/include/TextShadow.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040024#include "modules/skparagraph/include/TextStyle.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040025#include "modules/skparagraph/src/Run.h"
Ben Wagner4ca7a812020-05-28 13:48:18 -040026#include "src/core/SkSpan.h"
27
28#include <unicode/ubrk.h>
29#include <memory>
30#include <string>
31#include <vector>
Julia Lavrovaa3552c52019-05-30 16:12:56 -040032
33class SkCanvas;
34
35namespace skia {
36namespace textlayout {
37
Julia Lavrova149f22d2020-05-27 10:38:35 -040038enum CodeUnitFlags {
39 kNoCodeUnitFlag = 0x0,
40 kPartOfWhiteSpace = 0x1,
41 kGraphemeBreakBefore = 0x2,
42 kSoftLineBreakBefore = 0x4,
43 kHardLineBreakBefore = 0x8,
44};
45}
46}
47
48namespace sknonstd {
49template <> struct is_bitmask_enum<skia::textlayout::CodeUnitFlags> : std::true_type {};
50}
51
52namespace skia {
53namespace textlayout {
54
Ben Wagner4ca7a812020-05-28 13:48:18 -040055class LineMetrics;
56class TextLine;
57
Julia Lavrovaa3552c52019-05-30 16:12:56 -040058template <typename T> bool operator==(const SkSpan<T>& a, const SkSpan<T>& b) {
59 return a.size() == b.size() && a.begin() == b.begin();
60}
61
62template <typename T> bool operator<=(const SkSpan<T>& a, const SkSpan<T>& b) {
63 return a.begin() >= b.begin() && a.end() <= b.end();
64}
65
Julia Lavrova5207f352019-06-21 12:22:32 -040066template <typename TStyle>
67struct StyleBlock {
68 StyleBlock() : fRange(EMPTY_RANGE), fStyle() { }
69 StyleBlock(size_t start, size_t end, const TStyle& style) : fRange(start, end), fStyle(style) {}
70 StyleBlock(TextRange textRange, const TStyle& style) : fRange(textRange), fStyle(style) {}
71 void add(TextRange tail) {
72 SkASSERT(fRange.end == tail.start);
73 fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width());
74 }
75 TextRange fRange;
76 TStyle fStyle;
77};
78
Julia Lavrova2e30fde2019-10-09 09:43:02 -040079struct ResolvedFontDescriptor {
80
81 ResolvedFontDescriptor(TextIndex index, SkFont font)
82 : fFont(font), fTextStart(index) { }
83 SkFont fFont;
84 TextIndex fTextStart;
85};
86
Julia Lavrovac88a3bc2020-01-23 10:16:26 -050087struct BidiRegion {
88 BidiRegion(size_t start, size_t end, uint8_t dir)
89 : text(start, end), direction(dir) { }
90 TextRange text;
91 uint8_t direction;
92};
93
Julia Lavrovaa3552c52019-05-30 16:12:56 -040094class ParagraphImpl final : public Paragraph {
Julia Lavrovac2228562019-08-08 16:51:27 -040095
Julia Lavrovaa3552c52019-05-30 16:12:56 -040096public:
Julia Lavrova5207f352019-06-21 12:22:32 -040097
Julia Lavrovaa3552c52019-05-30 16:12:56 -040098 ParagraphImpl(const SkString& text,
99 ParagraphStyle style,
Julia Lavrova5207f352019-06-21 12:22:32 -0400100 SkTArray<Block, true> blocks,
Julia Lavrova916a9042019-08-08 16:51:27 -0400101 SkTArray<Placeholder, true> placeholders,
Julia Lavrova35f88222019-06-21 12:22:32 -0400102 sk_sp<FontCollection> fonts);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400103
104 ParagraphImpl(const std::u16string& utf16text,
Julia Lavrova916a9042019-08-08 16:51:27 -0400105 ParagraphStyle style,
106 SkTArray<Block, true> blocks,
107 SkTArray<Placeholder, true> placeholders,
108 sk_sp<FontCollection> fonts);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400109 ~ParagraphImpl() override;
110
111 void layout(SkScalar width) override;
112 void paint(SkCanvas* canvas, SkScalar x, SkScalar y) override;
113 std::vector<TextBox> getRectsForRange(unsigned start,
114 unsigned end,
115 RectHeightStyle rectHeightStyle,
116 RectWidthStyle rectWidthStyle) override;
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400117 std::vector<TextBox> getRectsForPlaceholders() override;
118 void getLineMetrics(std::vector<LineMetrics>&) override;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400119 PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override;
120 SkRange<size_t> getWordBoundary(unsigned offset) override;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400121
122 size_t lineNumber() override { return fLines.size(); }
123
Julia Lavrova5207f352019-06-21 12:22:32 -0400124 TextLine& addLine(SkVector offset, SkVector advance, TextRange text, TextRange textWithSpaces,
Julia Lavrova2ea20ea2020-01-22 10:56:53 -0500125 ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar widthWithSpaces,
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400126 InternalLineMetrics sizes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400127
Julia Lavrovaa40db422019-08-21 13:49:15 -0400128 SkSpan<const char> text() const { return SkSpan<const char>(fText.c_str(), fText.size()); }
Julia Lavrova5207f352019-06-21 12:22:32 -0400129 InternalState state() const { return fState; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400130 SkSpan<Run> runs() { return SkSpan<Run>(fRuns.data(), fRuns.size()); }
Julia Lavrova5207f352019-06-21 12:22:32 -0400131 SkSpan<Block> styles() {
132 return SkSpan<Block>(fTextStyles.data(), fTextStyles.size());
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400133 }
Julia Lavrovac0360582020-02-05 10:17:53 -0500134 SkSpan<Placeholder> placeholders() {
135 return SkSpan<Placeholder>(fPlaceholders.data(), fPlaceholders.size());
136 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400137 SkSpan<TextLine> lines() { return SkSpan<TextLine>(fLines.data(), fLines.size()); }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400138 const ParagraphStyle& paragraphStyle() const { return fParagraphStyle; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400139 SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); }
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -0400140 sk_sp<FontCollection> fontCollection() const { return fFontCollection; }
Julia Lavrova149f22d2020-05-27 10:38:35 -0400141 SkSpan<CodepointRepresentation> codepoints(){ return SkSpan<CodepointRepresentation>(fCodepoints.begin(), fCodepoints.size()); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400142 void formatLines(SkScalar maxWidth);
143
144 bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); }
145 bool strutForceHeight() const {
146 return paragraphStyle().getStrutStyle().getForceStrutHeight();
147 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400148 bool strutHeightOverride() const {
149 return paragraphStyle().getStrutStyle().getHeightOverride();
150 }
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400151 InternalLineMetrics strutMetrics() const { return fStrutMetrics; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400152
Julia Lavrova5207f352019-06-21 12:22:32 -0400153 SkSpan<const char> text(TextRange textRange);
154 SkSpan<Cluster> clusters(ClusterRange clusterRange);
155 Cluster& cluster(ClusterIndex clusterIndex);
Julia Lavrovae2c83a32020-06-08 11:48:46 -0400156 ClusterIndex clusterIndex(TextIndex textIndex) {
157 auto clusterIndex = this->fClustersIndexFromCodeUnit[textIndex];
158 SkASSERT(clusterIndex != EMPTY_INDEX);
159 return clusterIndex;
160 }
Mike Reedf6c48c02020-06-08 10:28:16 -0400161 Run& run(RunIndex runIndex) {
162 SkASSERT(runIndex < fRuns.size());
163 return fRuns[runIndex];
164 }
Julia Lavrovae2c83a32020-06-08 11:48:46 -0400165
Julia Lavrova526df262019-08-21 17:49:44 -0400166 Run& runByCluster(ClusterIndex clusterIndex);
Julia Lavrova5207f352019-06-21 12:22:32 -0400167 SkSpan<Block> blocks(BlockRange blockRange);
168 Block& block(BlockIndex blockIndex);
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400169 SkTArray<ResolvedFontDescriptor> resolvedFonts() const { return fFontSwitches; }
Julia Lavrova5207f352019-06-21 12:22:32 -0400170
171 void markDirty() override { fState = kUnknown; }
Julia Lavrova3281b962019-12-02 11:32:25 -0500172
173 int32_t unresolvedGlyphs() override;
174
Julia Lavrova5207f352019-06-21 12:22:32 -0400175 void setState(InternalState state);
Julia Lavrova5207f352019-06-21 12:22:32 -0400176 sk_sp<SkPicture> getPicture() { return fPicture; }
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400177 SkRect getBoundaries() const { return fOrigin; }
Julia Lavrova916a9042019-08-08 16:51:27 -0400178
Julia Lavrova8335ab62020-04-27 15:49:53 -0400179 SkScalar widthWithTrailingSpaces() { return fMaxWidthWithTrailingSpaces; }
180
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400181 void resetContext();
182 void resolveStrut();
Julia Lavrova149f22d2020-05-27 10:38:35 -0400183
184 bool computeCodeUnitProperties();
185 bool computeWords();
186 bool getBidiRegions();
187
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400188 void buildClusterTable();
Julia Lavrova8335ab62020-04-27 15:49:53 -0400189 void spaceGlyphs();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400190 bool shapeTextIntoEndlessLine();
191 void breakShapedTextIntoLines(SkScalar maxWidth);
192 void paintLinesIntoPicture();
193
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400194 void updateTextAlign(TextAlign textAlign) override;
195 void updateText(size_t from, SkString text) override;
196 void updateFontSize(size_t from, size_t to, SkScalar fontSize) override;
197 void updateForegroundPaint(size_t from, size_t to, SkPaint paint) override;
198 void updateBackgroundPaint(size_t from, size_t to, SkPaint paint) override;
199
Jason Simmons22bb52e2019-12-05 17:56:59 -0800200 InternalLineMetrics getEmptyMetrics() const { return fEmptyMetrics; }
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400201 InternalLineMetrics getStrutMetrics() const { return fStrutMetrics; }
202
Julia Lavrova90bfd1c2019-12-04 11:43:32 -0500203 BlockRange findAllBlocks(TextRange textRange);
204
Julia Lavrovaa0708e82020-02-28 12:14:58 -0500205 void resetShifts() {
206 for (auto& run : fRuns) {
207 run.resetJustificationShifts();
208 run.resetShifts();
209 }
210 }
211
Julia Lavrova149f22d2020-05-27 10:38:35 -0400212 using CodeUnitRangeVisitor = std::function<bool(TextRange textRange)>;
213 void forEachCodeUnitPropertyRange(CodeUnitFlags property, CodeUnitRangeVisitor visitor);
214 size_t getWhitespacesLength(TextRange textRange);
215
216 bool codeUnitHasProperty(size_t index, CodeUnitFlags property) const { return (fCodeUnitProperties[index] & property) == property; }
217
Julia Lavrova5207f352019-06-21 12:22:32 -0400218private:
219 friend class ParagraphBuilder;
220 friend class ParagraphCacheKey;
221 friend class ParagraphCacheValue;
222 friend class ParagraphCache;
223
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400224 friend class TextWrapper;
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400225 friend class OneLineShaper;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400226
Julia Lavrova9bd83512020-01-15 14:46:35 -0500227 void calculateBoundaries();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400228
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400229 void markGraphemes16();
Julia Lavrovac2228562019-08-08 16:51:27 -0400230
Jason Simmons22bb52e2019-12-05 17:56:59 -0800231 void computeEmptyMetrics();
232
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400233 // Input
Julia Lavrova5207f352019-06-21 12:22:32 -0400234 SkTArray<StyleBlock<SkScalar>> fLetterSpaceStyles;
235 SkTArray<StyleBlock<SkScalar>> fWordSpaceStyles;
236 SkTArray<StyleBlock<SkPaint>> fBackgroundStyles;
237 SkTArray<StyleBlock<SkPaint>> fForegroundStyles;
238 SkTArray<StyleBlock<std::vector<TextShadow>>> fShadowStyles;
239 SkTArray<StyleBlock<Decoration>> fDecorationStyles;
240 SkTArray<Block, true> fTextStyles; // TODO: take out only the font stuff
Julia Lavrova916a9042019-08-08 16:51:27 -0400241 SkTArray<Placeholder, true> fPlaceholders;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400242 SkString fText;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400243
244 // Internal structures
Julia Lavrova5207f352019-06-21 12:22:32 -0400245 InternalState fState;
Julia Lavrovaa0708e82020-02-28 12:14:58 -0500246 SkTArray<Run, false> fRuns; // kShaped
Julia Lavrova5207f352019-06-21 12:22:32 -0400247 SkTArray<Cluster, true> fClusters; // kClusterized (cached: text, word spacing, letter spacing, resolved fonts)
Julia Lavrova149f22d2020-05-27 10:38:35 -0400248 SkTArray<CodeUnitFlags> fCodeUnitProperties;
Julia Lavrovae2c83a32020-06-08 11:48:46 -0400249 SkTArray<size_t> fClustersIndexFromCodeUnit;
Julia Lavrova149f22d2020-05-27 10:38:35 -0400250 std::vector<size_t> fWords;
251 SkTArray<BidiRegion> fBidiRegions;
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400252 SkTArray<Grapheme, true> fGraphemes16;
Julia Lavrova149f22d2020-05-27 10:38:35 -0400253 SkTArray<CodepointRepresentation, true> fCodepoints;
Julia Lavrova3281b962019-12-02 11:32:25 -0500254 size_t fUnresolvedGlyphs;
Julia Lavrova5207f352019-06-21 12:22:32 -0400255
Ben Wagnerc0872212020-05-27 22:13:55 -0400256 SkTArray<TextLine, false> fLines; // kFormatted (cached: width, max lines, ellipsis, text align)
Julia Lavrova5207f352019-06-21 12:22:32 -0400257 sk_sp<SkPicture> fPicture; // kRecorded (cached: text styles)
258
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400259 SkTArray<ResolvedFontDescriptor> fFontSwitches;
260
Jason Simmons22bb52e2019-12-05 17:56:59 -0800261 InternalLineMetrics fEmptyMetrics;
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400262 InternalLineMetrics fStrutMetrics;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400263
Julia Lavrova9af5cc42019-06-19 13:32:01 -0400264 SkScalar fOldWidth;
Julia Lavrova5207f352019-06-21 12:22:32 -0400265 SkScalar fOldHeight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400266 SkScalar fMaxWidthWithTrailingSpaces;
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400267 SkRect fOrigin;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400268};
269} // namespace textlayout
270} // namespace skia
271
Julia Lavrova149f22d2020-05-27 10:38:35 -0400272
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400273#endif // ParagraphImpl_DEFINED