blob: ab960e030f6d3f67b91ac54dcc9571f0e95c6da4 [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"
Greg Danielf91aeb22019-06-18 09:58:02 -04006#include "include/private/SkTHash.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04007#include "modules/skparagraph/include/Paragraph.h"
8#include "modules/skparagraph/include/ParagraphStyle.h"
9#include "modules/skparagraph/include/TextStyle.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040010#include "modules/skparagraph/src/Run.h"
11#include "modules/skparagraph/src/TextLine.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040012
13class SkCanvas;
14
15namespace skia {
16namespace textlayout {
17
18template <typename T> bool operator==(const SkSpan<T>& a, const SkSpan<T>& b) {
19 return a.size() == b.size() && a.begin() == b.begin();
20}
21
22template <typename T> bool operator<=(const SkSpan<T>& a, const SkSpan<T>& b) {
23 return a.begin() >= b.begin() && a.end() <= b.end();
24}
25
26class ParagraphImpl final : public Paragraph {
27public:
28 ParagraphImpl(const SkString& text,
29 ParagraphStyle style,
30 std::vector<Block> blocks,
31 sk_sp<FontCollection> fonts)
32 : Paragraph(std::move(style), std::move(fonts))
33 , fText(text)
34 , fTextSpan(fText.c_str(), fText.size())
35 , fPicture(nullptr) {
36 fTextStyles.reserve(blocks.size());
37 for (auto& block : blocks) {
38 fTextStyles.emplace_back(
39 SkSpan<const char>(fTextSpan.begin() + block.fStart, block.fEnd - block.fStart),
40 block.fStyle);
41 }
42 }
43
44 ParagraphImpl(const std::u16string& utf16text,
45 ParagraphStyle style,
46 std::vector<Block> blocks,
47 sk_sp<FontCollection> fonts);
48 ~ParagraphImpl() override;
49
50 void layout(SkScalar width) override;
51 void paint(SkCanvas* canvas, SkScalar x, SkScalar y) override;
52 std::vector<TextBox> getRectsForRange(unsigned start,
53 unsigned end,
54 RectHeightStyle rectHeightStyle,
55 RectWidthStyle rectWidthStyle) override;
56 PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override;
57 SkRange<size_t> getWordBoundary(unsigned offset) override;
58 bool didExceedMaxLines() override {
59 return !fParagraphStyle.unlimited_lines() && fLines.size() > fParagraphStyle.getMaxLines();
60 }
61
62 size_t lineNumber() override { return fLines.size(); }
63
64 TextLine& addLine(SkVector offset, SkVector advance, SkSpan<const char> text,
65 SkSpan<const char> textWithSpaces, SkSpan<const Cluster> clusters,
66 size_t start, size_t end, LineMetrics sizes);
67
68 SkSpan<const char> text() const { return fTextSpan; }
69 SkSpan<Run> runs() { return SkSpan<Run>(fRuns.data(), fRuns.size()); }
70 SkSpan<TextBlock> styles() {
71 return SkSpan<TextBlock>(fTextStyles.data(), fTextStyles.size());
72 }
73 SkSpan<TextLine> lines() { return SkSpan<TextLine>(fLines.data(), fLines.size()); }
74 ParagraphStyle paragraphStyle() const { return fParagraphStyle; }
75 SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); }
76 void formatLines(SkScalar maxWidth);
77
78 bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); }
79 bool strutForceHeight() const {
80 return paragraphStyle().getStrutStyle().getForceStrutHeight();
81 }
82 LineMetrics strutMetrics() const { return fStrutMetrics; }
83
84private:
85 friend class ParagraphBuilder;
86
87 void resetContext();
88 void resolveStrut();
89 void buildClusterTable();
90 bool shapeTextIntoEndlessLine();
91 void breakShapedTextIntoLines(SkScalar maxWidth);
92 void paintLinesIntoPicture();
93
94 SkSpan<const TextBlock> findAllBlocks(SkSpan<const char> text);
95
96 // Input
97 SkTArray<TextBlock, true> fTextStyles;
98 SkString fText;
99 SkSpan<const char> fTextSpan;
100
101 // Internal structures
102 SkTArray<Run> fRuns;
103 SkTArray<Cluster, true> fClusters;
104 SkTArray<TextLine> fLines;
105 LineMetrics fStrutMetrics;
106
107 // Painting
108 sk_sp<SkPicture> fPicture;
109};
110} // namespace textlayout
111} // namespace skia
112
113#endif // ParagraphImpl_DEFINED