Julia Lavrova | a3552c5 | 2019-05-30 16:12:56 -0400 | [diff] [blame] | 1 | // Copyright 2019 Google LLC. |
| 2 | #ifndef ParagraphImpl_DEFINED |
| 3 | #define ParagraphImpl_DEFINED |
| 4 | |
Julia Lavrova | a3552c5 | 2019-05-30 16:12:56 -0400 | [diff] [blame] | 5 | #include "include/core/SkPicture.h" |
Greg Daniel | f91aeb2 | 2019-06-18 09:58:02 -0400 | [diff] [blame^] | 6 | #include "include/private/SkTHash.h" |
Julia Lavrova | a3552c5 | 2019-05-30 16:12:56 -0400 | [diff] [blame] | 7 | #include "modules/skparagraph/include/Paragraph.h" |
| 8 | #include "modules/skparagraph/include/ParagraphStyle.h" |
| 9 | #include "modules/skparagraph/include/TextStyle.h" |
Greg Daniel | f91aeb2 | 2019-06-18 09:58:02 -0400 | [diff] [blame^] | 10 | #include "modules/skparagraph/src/Run.h" |
| 11 | #include "modules/skparagraph/src/TextLine.h" |
Julia Lavrova | a3552c5 | 2019-05-30 16:12:56 -0400 | [diff] [blame] | 12 | |
| 13 | class SkCanvas; |
| 14 | |
| 15 | namespace skia { |
| 16 | namespace textlayout { |
| 17 | |
| 18 | template <typename T> bool operator==(const SkSpan<T>& a, const SkSpan<T>& b) { |
| 19 | return a.size() == b.size() && a.begin() == b.begin(); |
| 20 | } |
| 21 | |
| 22 | template <typename T> bool operator<=(const SkSpan<T>& a, const SkSpan<T>& b) { |
| 23 | return a.begin() >= b.begin() && a.end() <= b.end(); |
| 24 | } |
| 25 | |
| 26 | class ParagraphImpl final : public Paragraph { |
| 27 | public: |
| 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 | |
| 84 | private: |
| 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 |