blob: 4bd3d904be6dd3c9c7aa04a80bda43548e352a38 [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"
John Stilesc88a6ac2020-07-27 08:41:27 -040026#include "modules/skparagraph/src/TextLine.h"
Julia Lavrova90787fe2020-07-20 17:32:03 +000027#include "modules/skshaper/src/SkUnicode.h"
Ben Wagner4ca7a812020-05-28 13:48:18 -040028#include "src/core/SkSpan.h"
29
Ben Wagner4ca7a812020-05-28 13:48:18 -040030#include <memory>
31#include <string>
32#include <vector>
Julia Lavrovaa3552c52019-05-30 16:12:56 -040033
34class SkCanvas;
35
36namespace skia {
37namespace textlayout {
38
Julia Lavrova149f22d2020-05-27 10:38:35 -040039enum CodeUnitFlags {
40 kNoCodeUnitFlag = 0x0,
41 kPartOfWhiteSpace = 0x1,
Julia Lavrovac4d49052020-06-15 10:20:08 -040042 kGraphemeStart = 0x2,
Julia Lavrova149f22d2020-05-27 10:38:35 -040043 kSoftLineBreakBefore = 0x4,
44 kHardLineBreakBefore = 0x8,
45};
John Stilesa6841be2020-08-06 14:11:56 -040046} // namespace textlayout
47} // namespace skia
Julia Lavrova149f22d2020-05-27 10:38:35 -040048
49namespace sknonstd {
50template <> struct is_bitmask_enum<skia::textlayout::CodeUnitFlags> : std::true_type {};
John Stilesa6841be2020-08-06 14:11:56 -040051} // namespace sknonstd
Julia Lavrova149f22d2020-05-27 10:38:35 -040052
53namespace skia {
54namespace textlayout {
55
Ben Wagner4ca7a812020-05-28 13:48:18 -040056class LineMetrics;
57class TextLine;
58
Julia Lavrovaa3552c52019-05-30 16:12:56 -040059template <typename T> bool operator==(const SkSpan<T>& a, const SkSpan<T>& b) {
60 return a.size() == b.size() && a.begin() == b.begin();
61}
62
63template <typename T> bool operator<=(const SkSpan<T>& a, const SkSpan<T>& b) {
64 return a.begin() >= b.begin() && a.end() <= b.end();
65}
66
Julia Lavrova5207f352019-06-21 12:22:32 -040067template <typename TStyle>
68struct StyleBlock {
69 StyleBlock() : fRange(EMPTY_RANGE), fStyle() { }
70 StyleBlock(size_t start, size_t end, const TStyle& style) : fRange(start, end), fStyle(style) {}
71 StyleBlock(TextRange textRange, const TStyle& style) : fRange(textRange), fStyle(style) {}
72 void add(TextRange tail) {
73 SkASSERT(fRange.end == tail.start);
74 fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width());
75 }
76 TextRange fRange;
77 TStyle fStyle;
78};
79
Julia Lavrova2e30fde2019-10-09 09:43:02 -040080struct ResolvedFontDescriptor {
81
82 ResolvedFontDescriptor(TextIndex index, SkFont font)
83 : fFont(font), fTextStart(index) { }
84 SkFont fFont;
85 TextIndex fTextStart;
86};
Julia Lavrova90787fe2020-07-20 17:32:03 +000087/*
Julia Lavrovac88a3bc2020-01-23 10:16:26 -050088struct BidiRegion {
89 BidiRegion(size_t start, size_t end, uint8_t dir)
90 : text(start, end), direction(dir) { }
91 TextRange text;
92 uint8_t direction;
93};
Julia Lavrova90787fe2020-07-20 17:32:03 +000094*/
Julia Lavrovaa3552c52019-05-30 16:12:56 -040095class ParagraphImpl final : public Paragraph {
Julia Lavrovac2228562019-08-08 16:51:27 -040096
Julia Lavrovaa3552c52019-05-30 16:12:56 -040097public:
Julia Lavrova5207f352019-06-21 12:22:32 -040098
Julia Lavrovaa3552c52019-05-30 16:12:56 -040099 ParagraphImpl(const SkString& text,
100 ParagraphStyle style,
Julia Lavrova5207f352019-06-21 12:22:32 -0400101 SkTArray<Block, true> blocks,
Julia Lavrova916a9042019-08-08 16:51:27 -0400102 SkTArray<Placeholder, true> placeholders,
Julia Lavrova05ce2812020-09-01 20:51:05 +0000103 sk_sp<FontCollection> fonts);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400104
105 ParagraphImpl(const std::u16string& utf16text,
Julia Lavrova916a9042019-08-08 16:51:27 -0400106 ParagraphStyle style,
107 SkTArray<Block, true> blocks,
108 SkTArray<Placeholder, true> placeholders,
Julia Lavrova05ce2812020-09-01 20:51:05 +0000109 sk_sp<FontCollection> fonts);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400110 ~ParagraphImpl() override;
111
112 void layout(SkScalar width) override;
113 void paint(SkCanvas* canvas, SkScalar x, SkScalar y) override;
114 std::vector<TextBox> getRectsForRange(unsigned start,
115 unsigned end,
116 RectHeightStyle rectHeightStyle,
117 RectWidthStyle rectWidthStyle) override;
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400118 std::vector<TextBox> getRectsForPlaceholders() override;
119 void getLineMetrics(std::vector<LineMetrics>&) override;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400120 PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override;
121 SkRange<size_t> getWordBoundary(unsigned offset) override;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400122
123 size_t lineNumber() override { return fLines.size(); }
124
Julia Lavrova5207f352019-06-21 12:22:32 -0400125 TextLine& addLine(SkVector offset, SkVector advance, TextRange text, TextRange textWithSpaces,
Julia Lavrova2ea20ea2020-01-22 10:56:53 -0500126 ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar widthWithSpaces,
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400127 InternalLineMetrics sizes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400128
Julia Lavrovaa40db422019-08-21 13:49:15 -0400129 SkSpan<const char> text() const { return SkSpan<const char>(fText.c_str(), fText.size()); }
Julia Lavrova5207f352019-06-21 12:22:32 -0400130 InternalState state() const { return fState; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400131 SkSpan<Run> runs() { return SkSpan<Run>(fRuns.data(), fRuns.size()); }
Julia Lavrova5207f352019-06-21 12:22:32 -0400132 SkSpan<Block> styles() {
133 return SkSpan<Block>(fTextStyles.data(), fTextStyles.size());
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400134 }
Julia Lavrovac0360582020-02-05 10:17:53 -0500135 SkSpan<Placeholder> placeholders() {
136 return SkSpan<Placeholder>(fPlaceholders.data(), fPlaceholders.size());
137 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400138 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);
Julia Lavrovac4d49052020-06-15 10:20:08 -0400143 void ensureUTF16Mapping();
144 TextIndex findGraphemeStart(TextIndex index);
145 size_t getUTF16Index(TextIndex index) {
146 return fUTF16IndexForUTF8Index[index];
147 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400148
149 bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); }
150 bool strutForceHeight() const {
151 return paragraphStyle().getStrutStyle().getForceStrutHeight();
152 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400153 bool strutHeightOverride() const {
154 return paragraphStyle().getStrutStyle().getHeightOverride();
155 }
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400156 InternalLineMetrics strutMetrics() const { return fStrutMetrics; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400157
Julia Lavrova5207f352019-06-21 12:22:32 -0400158 SkSpan<const char> text(TextRange textRange);
159 SkSpan<Cluster> clusters(ClusterRange clusterRange);
160 Cluster& cluster(ClusterIndex clusterIndex);
Julia Lavrovae2c83a32020-06-08 11:48:46 -0400161 ClusterIndex clusterIndex(TextIndex textIndex) {
162 auto clusterIndex = this->fClustersIndexFromCodeUnit[textIndex];
163 SkASSERT(clusterIndex != EMPTY_INDEX);
164 return clusterIndex;
165 }
Mike Reedf6c48c02020-06-08 10:28:16 -0400166 Run& run(RunIndex runIndex) {
167 SkASSERT(runIndex < fRuns.size());
168 return fRuns[runIndex];
169 }
Julia Lavrovae2c83a32020-06-08 11:48:46 -0400170
Julia Lavrova526df262019-08-21 17:49:44 -0400171 Run& runByCluster(ClusterIndex clusterIndex);
Julia Lavrova5207f352019-06-21 12:22:32 -0400172 SkSpan<Block> blocks(BlockRange blockRange);
173 Block& block(BlockIndex blockIndex);
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400174 SkTArray<ResolvedFontDescriptor> resolvedFonts() const { return fFontSwitches; }
Julia Lavrova5207f352019-06-21 12:22:32 -0400175
176 void markDirty() override { fState = kUnknown; }
Julia Lavrova3281b962019-12-02 11:32:25 -0500177
178 int32_t unresolvedGlyphs() override;
179
Julia Lavrova5207f352019-06-21 12:22:32 -0400180 void setState(InternalState state);
Julia Lavrova5207f352019-06-21 12:22:32 -0400181 sk_sp<SkPicture> getPicture() { return fPicture; }
Julia Lavrova916a9042019-08-08 16:51:27 -0400182
Julia Lavrova8335ab62020-04-27 15:49:53 -0400183 SkScalar widthWithTrailingSpaces() { return fMaxWidthWithTrailingSpaces; }
184
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400185 void resetContext();
186 void resolveStrut();
Julia Lavrova149f22d2020-05-27 10:38:35 -0400187
188 bool computeCodeUnitProperties();
Julia Lavrova149f22d2020-05-27 10:38:35 -0400189
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400190 void buildClusterTable();
Julia Lavrova8335ab62020-04-27 15:49:53 -0400191 void spaceGlyphs();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400192 bool shapeTextIntoEndlessLine();
193 void breakShapedTextIntoLines(SkScalar maxWidth);
Julia Lavrovab6030fb2020-09-08 11:01:49 -0400194 void paintLinesIntoPicture(SkScalar x, SkScalar y);
195 void paintLines(SkCanvas* canvas, SkScalar x, SkScalar y);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400196
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400197 void updateTextAlign(TextAlign textAlign) override;
198 void updateText(size_t from, SkString text) override;
199 void updateFontSize(size_t from, size_t to, SkScalar fontSize) override;
200 void updateForegroundPaint(size_t from, size_t to, SkPaint paint) override;
201 void updateBackgroundPaint(size_t from, size_t to, SkPaint paint) override;
202
Jason Simmons22bb52e2019-12-05 17:56:59 -0800203 InternalLineMetrics getEmptyMetrics() const { return fEmptyMetrics; }
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400204 InternalLineMetrics getStrutMetrics() const { return fStrutMetrics; }
205
Julia Lavrova90bfd1c2019-12-04 11:43:32 -0500206 BlockRange findAllBlocks(TextRange textRange);
207
Julia Lavrovaa0708e82020-02-28 12:14:58 -0500208 void resetShifts() {
209 for (auto& run : fRuns) {
210 run.resetJustificationShifts();
211 run.resetShifts();
212 }
213 }
214
Julia Lavrova149f22d2020-05-27 10:38:35 -0400215 using CodeUnitRangeVisitor = std::function<bool(TextRange textRange)>;
216 void forEachCodeUnitPropertyRange(CodeUnitFlags property, CodeUnitRangeVisitor visitor);
217 size_t getWhitespacesLength(TextRange textRange);
218
219 bool codeUnitHasProperty(size_t index, CodeUnitFlags property) const { return (fCodeUnitProperties[index] & property) == property; }
220
Julia Lavrova05ce2812020-09-01 20:51:05 +0000221 SkUnicode* getICU() { return fICU.get(); }
Julia Lavrova90787fe2020-07-20 17:32:03 +0000222
Julia Lavrova5207f352019-06-21 12:22:32 -0400223private:
224 friend class ParagraphBuilder;
225 friend class ParagraphCacheKey;
226 friend class ParagraphCacheValue;
227 friend class ParagraphCache;
228
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400229 friend class TextWrapper;
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400230 friend class OneLineShaper;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400231
Jason Simmons22bb52e2019-12-05 17:56:59 -0800232 void computeEmptyMetrics();
233
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400234 // Input
Julia Lavrova5207f352019-06-21 12:22:32 -0400235 SkTArray<StyleBlock<SkScalar>> fLetterSpaceStyles;
236 SkTArray<StyleBlock<SkScalar>> fWordSpaceStyles;
237 SkTArray<StyleBlock<SkPaint>> fBackgroundStyles;
238 SkTArray<StyleBlock<SkPaint>> fForegroundStyles;
239 SkTArray<StyleBlock<std::vector<TextShadow>>> fShadowStyles;
240 SkTArray<StyleBlock<Decoration>> fDecorationStyles;
241 SkTArray<Block, true> fTextStyles; // TODO: take out only the font stuff
Julia Lavrova916a9042019-08-08 16:51:27 -0400242 SkTArray<Placeholder, true> fPlaceholders;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400243 SkString fText;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400244
245 // Internal structures
Julia Lavrova5207f352019-06-21 12:22:32 -0400246 InternalState fState;
Julia Lavrovaa0708e82020-02-28 12:14:58 -0500247 SkTArray<Run, false> fRuns; // kShaped
Julia Lavrova5207f352019-06-21 12:22:32 -0400248 SkTArray<Cluster, true> fClusters; // kClusterized (cached: text, word spacing, letter spacing, resolved fonts)
Julia Lavrova149f22d2020-05-27 10:38:35 -0400249 SkTArray<CodeUnitFlags> fCodeUnitProperties;
Julia Lavrovae2c83a32020-06-08 11:48:46 -0400250 SkTArray<size_t> fClustersIndexFromCodeUnit;
Julia Lavrova149f22d2020-05-27 10:38:35 -0400251 std::vector<size_t> fWords;
Julia Lavrova1798f4f2020-08-26 14:22:48 +0000252 std::vector<SkUnicode::BidiRegion> fBidiRegions;
Julia Lavrovac4d49052020-06-15 10:20:08 -0400253 // These two arrays are used in measuring methods (getRectsForRange, getGlyphPositionAtCoordinate)
254 // They are filled lazily whenever they need and cached
255 SkTArray<TextIndex, true> fUTF8IndexForUTF16Index;
256 SkTArray<size_t, true> fUTF16IndexForUTF8Index;
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 Lavrova90787fe2020-07-20 17:32:03 +0000270
Julia Lavrova05ce2812020-09-01 20:51:05 +0000271 std::unique_ptr<SkUnicode> fICU;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400272};
273} // namespace textlayout
274} // namespace skia
275
Julia Lavrova149f22d2020-05-27 10:38:35 -0400276
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400277#endif // ParagraphImpl_DEFINED